001package jmri.jmrit.dispatcher; 002 003import java.awt.Container; 004import java.awt.FlowLayout; 005import java.awt.event.ActionEvent; 006import java.awt.event.ActionListener; 007import java.util.ArrayList; 008import java.util.Enumeration; 009 010import javax.swing.BorderFactory; 011import javax.swing.BoxLayout; 012import javax.swing.ButtonGroup; 013import javax.swing.JButton; 014import javax.swing.JCheckBox; 015import javax.swing.JCheckBoxMenuItem; 016import javax.swing.JComboBox; 017import javax.swing.JLabel; 018import javax.swing.JMenu; 019import javax.swing.JMenuItem; 020import javax.swing.JPanel; 021import javax.swing.JRadioButton; 022import javax.swing.JSeparator; 023import javax.swing.JSpinner; 024import javax.swing.SpinnerNumberModel; 025 026import jmri.InstanceManager; 027import jmri.Scale; 028import jmri.ScaleManager; 029import jmri.implementation.SignalSpeedMap; 030import jmri.jmrit.dispatcher.DispatcherFrame.TrainsFrom; 031import jmri.jmrit.display.EditorManager; 032import jmri.jmrit.display.layoutEditor.LayoutEditor; 033import jmri.util.JmriJFrame; 034import jmri.util.swing.JmriJOptionPane; 035 036/** 037 * Set up and processes items in the Dispatcher Options menu. 038 * 039 * @author Dave Duchamp Copyright (C) 2008 040 */ 041public class OptionsMenu extends JMenu { 042 043 public OptionsMenu(DispatcherFrame f) { 044 dispatcher = f; 045 this.setText(Bundle.getMessage("MenuOptions")); 046 autoDispatchItem = new JCheckBoxMenuItem(Bundle.getMessage("AutoDispatchItem")); 047 this.add(autoDispatchItem); 048 autoDispatchItem.addActionListener(new ActionListener() { 049 @Override 050 public void actionPerformed(ActionEvent event) { 051 handleAutoDispatch(event); 052 } 053 }); 054 autoTurnoutsItem = new JCheckBoxMenuItem(Bundle.getMessage("AutoTurnoutsItem")); 055 this.add(autoTurnoutsItem); 056 autoTurnoutsItem.addActionListener(new ActionListener() { 057 @Override 058 public void actionPerformed(ActionEvent event) { 059 handleAutoTurnouts(event); 060 } 061 }); 062 JMenuItem optionWindowItem = new JMenuItem(Bundle.getMessage("OptionWindowItem") + "..."); 063 this.add(optionWindowItem); 064 optionWindowItem.addActionListener(new ActionListener() { 065 @Override 066 public void actionPerformed(ActionEvent event) { 067 optionWindowRequested(event); 068 } 069 }); 070 JMenuItem saveOptionsItem = new JMenuItem(Bundle.getMessage("SaveOptionsItem")); 071 this.add(saveOptionsItem); 072 saveOptionsItem.addActionListener(new ActionListener() { 073 @Override 074 public void actionPerformed(ActionEvent event) { 075 saveRequested(event); 076 } 077 }); 078 initializeMenu(); 079 } 080 081 protected DispatcherFrame dispatcher = null; 082 083 // Option menu items 084 private JCheckBoxMenuItem autoDispatchItem = null; 085 private JCheckBoxMenuItem autoTurnoutsItem = null; 086 087 // Initialize check box items in menu from Dispatcher 088 public void initializeMenu() { 089 autoDispatchItem.setSelected(dispatcher.getAutoAllocate()); 090 autoTurnoutsItem.setSelected(dispatcher.getAutoTurnouts()); 091 } 092 093 private void handleAutoDispatch(ActionEvent e) { 094 boolean set = autoDispatchItem.isSelected(); 095 dispatcher.setAutoAllocate(set); 096 } 097 098 private void handleAutoTurnouts(ActionEvent e) { 099 boolean set = autoTurnoutsItem.isSelected(); 100 dispatcher.setAutoTurnouts(set); 101 } 102 103 // options window items 104 JmriJFrame optionsFrame = null; 105 Container optionsPane = null; 106 JCheckBox useConnectivityCheckBox = new JCheckBox(Bundle.getMessage("UseConnectivity")); 107 ArrayList<LayoutEditor> layoutEditorList = new ArrayList<>(); 108 109 JCheckBox autoAllocateCheckBox = new JCheckBox(Bundle.getMessage("AutoAllocateBox")); 110 JCheckBox autoTurnoutsCheckBox = new JCheckBox(Bundle.getMessage("AutoTurnoutsBox")); 111 JRadioButton trainsFromRoster = new JRadioButton(Bundle.getMessage("TrainsFromRoster")); 112 JRadioButton trainsFromTrains = new JRadioButton(Bundle.getMessage("TrainsFromTrains")); 113 JRadioButton trainsFromUser = new JRadioButton(Bundle.getMessage("TrainsFromUser")); 114 JComboBox<String> signalTypeBox; 115 JCheckBox detectionCheckBox = new JCheckBox(Bundle.getMessage("DetectionBox")); 116 JCheckBox setSSLDirectionalSensorsCheckBox = new JCheckBox(Bundle.getMessage("SetSSLDirectionSensorsBox")); 117 JCheckBox shortNameCheckBox = new JCheckBox(Bundle.getMessage("ShortNameBox")); 118 JCheckBox nameInBlockCheckBox = new JCheckBox(Bundle.getMessage("NameInBlockBox")); 119 JCheckBox rosterInBlockCheckBox = new JCheckBox(Bundle.getMessage("RosterInBlockBox")); 120 JCheckBox extraColorForAllocatedCheckBox = new JCheckBox(Bundle.getMessage("ExtraColorForAllocatedBox")); 121 JCheckBox nameInAllocatedBlockCheckBox = new JCheckBox(Bundle.getMessage("NameInAllocatedBlockBox")); 122 JCheckBox supportVSDecoderCheckBox = new JCheckBox(Bundle.getMessage("SupportVSDecoder")); 123 JComboBox<Scale> layoutScaleBox = new JComboBox<>(); 124 JRadioButton scaleFeet = new JRadioButton(Bundle.getMessage("ScaleFeet")); 125 JRadioButton scaleMeters = new JRadioButton(Bundle.getMessage("ScaleMeters")); 126 JCheckBox openDispatcherWithPanel = new JCheckBox(Bundle.getMessage("OpenDispatcherWithPanelBox")); 127 JSpinner minThrottleIntervalSpinner = new JSpinner(new SpinnerNumberModel(100, 20, 1000, 1)); 128 JSpinner fullRampTimeSpinner = new JSpinner(new SpinnerNumberModel(5000, 1000, 20000, 1)); 129 JCheckBox trustKnownTurnoutsCheckBox = new JCheckBox(Bundle.getMessage("trustKnownTurnouts")); 130 JComboBox<String> stoppingSpeedBox = new JComboBox<>(); 131 132 String[] signalTypes = {Bundle.getMessage("SignalType1"), Bundle.getMessage("SignalType2"), Bundle.getMessage("SignalType3")}; 133 134 private void optionWindowRequested(ActionEvent e) { 135 if (optionsFrame == null) { 136 optionsFrame = new JmriJFrame(Bundle.getMessage("OptionWindowItem"), false, true); 137 optionsFrame.addHelpMenu("package.jmri.jmrit.dispatcher.Options", true); 138 optionsPane = optionsFrame.getContentPane(); 139 optionsPane.setLayout(new BoxLayout(optionsFrame.getContentPane(), BoxLayout.Y_AXIS)); 140 JPanel p1 = new JPanel(); 141 p1.setLayout(new FlowLayout()); 142 p1.add(useConnectivityCheckBox); 143 useConnectivityCheckBox.setToolTipText(Bundle.getMessage("UseConnectivityHint")); 144 signalTypeBox = new JComboBox<>(signalTypes); 145 p1.add(signalTypeBox); 146 signalTypeBox.setToolTipText(Bundle.getMessage("SignalTypeHint")); 147 optionsPane.add(p1); 148 JPanel p2 = new JPanel(); 149 p2.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("TrainsFrom"))); 150 p2.setLayout(new FlowLayout()); 151 ButtonGroup trainsGroup = new ButtonGroup(); 152 p2.add(trainsFromRoster); 153 trainsFromRoster.setToolTipText(Bundle.getMessage("TrainsFromRosterHint")); 154 trainsGroup.add(trainsFromRoster); 155 156 ActionListener useRosterEntryListener = new ActionListener() { 157 @Override 158 public void actionPerformed(ActionEvent e) { 159 if (trainsFromRoster.isSelected()) { 160 rosterInBlockCheckBox.setEnabled(true); 161 if (nameInBlockCheckBox.isSelected() && e.getSource() == nameInBlockCheckBox) { 162 rosterInBlockCheckBox.setSelected(false); 163 } else if (rosterInBlockCheckBox.isSelected() && e.getSource() == rosterInBlockCheckBox) { 164 nameInBlockCheckBox.setSelected(false); 165 } 166 } else { 167 rosterInBlockCheckBox.setEnabled(false); 168 } 169 } 170 }; 171 trainsFromRoster.addActionListener(useRosterEntryListener); 172 p2.add(new JLabel(" ")); 173 p2.add(trainsFromTrains); 174 trainsFromTrains.setToolTipText(Bundle.getMessage("TrainsFromTrainsHint")); 175 trainsFromTrains.addActionListener(useRosterEntryListener); 176 trainsGroup.add(trainsFromTrains); 177 p2.add(new JLabel(" ")); 178 p2.add(trainsFromUser); 179 trainsFromUser.setToolTipText(Bundle.getMessage("TrainsFromUserHint")); 180 trainsFromUser.addActionListener(useRosterEntryListener); 181 trainsGroup.add(trainsFromUser); 182 optionsPane.add(p2); 183 JPanel p3 = new JPanel(); 184 p3.setLayout(new FlowLayout()); 185 p3.add(detectionCheckBox); 186 detectionCheckBox.setToolTipText(Bundle.getMessage("DetectionBoxHint")); 187 optionsPane.add(p3); 188 JPanel p3A = new JPanel(); 189 p3A.setLayout(new FlowLayout()); 190 p3A.add(setSSLDirectionalSensorsCheckBox); 191 setSSLDirectionalSensorsCheckBox.setToolTipText(Bundle.getMessage("SetSSLDirectionSensorsBoxHint")); 192 optionsPane.add(p3A); 193 JPanel p4 = new JPanel(); 194 p4.setLayout(new FlowLayout()); 195 p4.add(autoAllocateCheckBox); 196 autoAllocateCheckBox.setToolTipText(Bundle.getMessage("AutoAllocateBoxHint")); 197 optionsPane.add(p4); 198 JPanel p5 = new JPanel(); 199 p5.setLayout(new FlowLayout()); 200 p5.add(autoTurnoutsCheckBox); 201 autoTurnoutsCheckBox.setToolTipText(Bundle.getMessage("AutoTurnoutsBoxHint")); 202 optionsPane.add(p5); 203 JPanel p16 = new JPanel(); 204 p16.setLayout(new FlowLayout()); 205 p16.add(trustKnownTurnoutsCheckBox); 206 trustKnownTurnoutsCheckBox.setToolTipText(Bundle.getMessage("trustKnownTurnoutsHint")); 207 optionsPane.add(p16); 208 JPanel p6 = new JPanel(); 209 p6.setLayout(new FlowLayout()); 210 p6.add(shortNameCheckBox); 211 shortNameCheckBox.setToolTipText(Bundle.getMessage("ShortNameBoxHint")); 212 optionsPane.add(p6); 213 JPanel p7 = new JPanel(); 214 p7.setLayout(new FlowLayout()); 215 p7.add(nameInBlockCheckBox); 216 nameInBlockCheckBox.setToolTipText(Bundle.getMessage("NameInBlockBoxHint")); 217 nameInBlockCheckBox.addActionListener(useRosterEntryListener); 218 optionsPane.add(p7); 219 JPanel p7b = new JPanel(); 220 p7b.setLayout(new FlowLayout()); 221 p7b.add(rosterInBlockCheckBox); 222 rosterInBlockCheckBox.setToolTipText(Bundle.getMessage("RosterInBlockBoxHint")); 223 rosterInBlockCheckBox.addActionListener(useRosterEntryListener); 224 optionsPane.add(p7b); 225 226 JPanel p10 = new JPanel(); 227 p10.setLayout(new FlowLayout()); 228 p10.add(extraColorForAllocatedCheckBox); 229 extraColorForAllocatedCheckBox.setToolTipText(Bundle.getMessage("ExtraColorForAllocatedBoxHint")); 230 optionsPane.add(p10); 231 JPanel p11 = new JPanel(); 232 p11.setLayout(new FlowLayout()); 233 p11.add(nameInAllocatedBlockCheckBox); 234 nameInAllocatedBlockCheckBox.setToolTipText(Bundle.getMessage("NameInAllocatedBlockBoxHint")); 235 optionsPane.add(p11); 236 JPanel p13 = new JPanel(); 237 p13.setLayout(new FlowLayout()); 238 p13.add(supportVSDecoderCheckBox); 239 supportVSDecoderCheckBox.setToolTipText(Bundle.getMessage("SupportVSDecoderBoxHint")); 240 optionsPane.add(p13); 241 JPanel p8 = new JPanel(); 242 initializeScaleCombo(); 243 p8.add(new JLabel(Bundle.getMessage("LabelLayoutScale"))); 244 p8.add(layoutScaleBox); 245 layoutScaleBox.setToolTipText(Bundle.getMessage("ScaleBoxHint")); 246 optionsPane.add(p8); 247 JPanel p12 = new JPanel(); 248 p12.setLayout(new FlowLayout()); 249 p12.add(new JLabel(Bundle.getMessage("Units") + " ")); 250 ButtonGroup scaleGroup = new ButtonGroup(); 251 p12.add(scaleFeet); 252 scaleFeet.setToolTipText(Bundle.getMessage("ScaleFeetHint")); 253 scaleGroup.add(scaleFeet); 254 p12.add(new JLabel(" ")); 255 p12.add(scaleMeters); 256 scaleMeters.setToolTipText(Bundle.getMessage("ScaleMetersHint")); 257 scaleGroup.add(scaleMeters); 258 optionsPane.add(p12); 259 260 JPanel p14 = new JPanel(); 261 initializeStoppingSpeedCombo(); 262 p14.add(new JLabel(Bundle.getMessage("LabelStoppingSpeed"))); 263 p14.add(stoppingSpeedBox); 264 stoppingSpeedBox.setToolTipText(Bundle.getMessage("StoppingSpeedHint")); 265 optionsPane.add(p14); 266 267 JPanel p15 = new JPanel(); 268 p15.setLayout(new FlowLayout()); 269 p15.add(new JLabel(Bundle.getMessage("minThrottleInterval") + ":")); 270 minThrottleIntervalSpinner.setToolTipText(Bundle.getMessage("minThrottleIntervalHint")); 271 p15.add(minThrottleIntervalSpinner); 272 p15.add(new JLabel(Bundle.getMessage("LabelMilliseconds"))); 273 optionsPane.add(p15); 274 275 JPanel p17 = new JPanel(); 276 p17.setLayout(new FlowLayout()); 277 p17.add(new JLabel(Bundle.getMessage("fullRampTime") + " :")); 278 fullRampTimeSpinner.setToolTipText(Bundle.getMessage("fullRampTimeHint", Bundle.getMessage("RAMP_FAST"))); 279 p17.add(fullRampTimeSpinner); 280 p17.add(new JLabel(Bundle.getMessage("LabelMilliseconds"))); 281 optionsPane.add(p17); 282 283 JPanel p18 = new JPanel(); 284 p18.setLayout(new FlowLayout()); 285 p18.add(openDispatcherWithPanel); 286 openDispatcherWithPanel.setToolTipText(Bundle.getMessage("OpenDispatcherWithPanelBoxHint")); 287 optionsPane.add(p18); 288 289 optionsPane.add(new JSeparator()); 290 JPanel p9 = new JPanel(); 291 p9.setLayout(new FlowLayout()); 292 JButton cancelButton = null; 293 p9.add(cancelButton = new JButton(Bundle.getMessage("ButtonCancel"))); 294 cancelButton.addActionListener(new ActionListener() { 295 @Override 296 public void actionPerformed(ActionEvent e) { 297 cancelOptions(e); 298 } 299 }); 300 cancelButton.setToolTipText(Bundle.getMessage("CancelButtonHint2")); 301 p9.add(new JLabel(" ")); 302 JButton applyButton = null; 303 p9.add(applyButton = new JButton(Bundle.getMessage("ButtonApply"))); 304 applyButton.addActionListener(new ActionListener() { 305 @Override 306 public void actionPerformed(ActionEvent e) { 307 applyOptions(e); 308 } 309 }); 310 applyButton.setToolTipText(Bundle.getMessage("ApplyButtonHint")); 311 optionsPane.add(p9); 312 } 313 314 initializeLayoutEditorList(); 315 useConnectivityCheckBox.setEnabled(!layoutEditorList.isEmpty()); 316 useConnectivityCheckBox.setSelected(dispatcher.getUseConnectivity()); 317 318 signalTypeBox.setSelectedIndex(dispatcher.getSignalType()); 319 switch (dispatcher.getTrainsFrom()) { 320 case TRAINSFROMROSTER: 321 trainsFromRoster.setSelected(true); 322 break; 323 case TRAINSFROMOPS: 324 trainsFromTrains.setSelected(true); 325 break; 326 case TRAINSFROMUSER: 327 default: 328 trainsFromUser.setSelected(true); 329 } 330 detectionCheckBox.setSelected(dispatcher.getHasOccupancyDetection()); 331 setSSLDirectionalSensorsCheckBox.setSelected(dispatcher.getSetSSLDirectionalSensors()); 332 autoAllocateCheckBox.setSelected(dispatcher.getAutoAllocate()); 333 autoTurnoutsCheckBox.setSelected(dispatcher.getAutoTurnouts()); 334 trustKnownTurnoutsCheckBox.setSelected(dispatcher.getTrustKnownTurnouts()); 335 shortNameCheckBox.setSelected(dispatcher.getShortActiveTrainNames()); 336 nameInBlockCheckBox.setSelected(dispatcher.getShortNameInBlock()); 337 rosterInBlockCheckBox.setSelected(dispatcher.getRosterEntryInBlock()); 338 extraColorForAllocatedCheckBox.setSelected(dispatcher.getExtraColorForAllocated()); 339 nameInAllocatedBlockCheckBox.setSelected(dispatcher.getNameInAllocatedBlock()); 340 supportVSDecoderCheckBox.setSelected(dispatcher.getSupportVSDecoder()); 341 scaleMeters.setSelected(dispatcher.getUseScaleMeters()); 342 scaleFeet.setSelected(!dispatcher.getUseScaleMeters()); 343 minThrottleIntervalSpinner.setValue(dispatcher.getMinThrottleInterval()); 344 fullRampTimeSpinner.setValue(dispatcher.getFullRampTime()); 345 346 boolean openDispatcher = false; 347 for (LayoutEditor panel : layoutEditorList) { 348 if (panel.getOpenDispatcherOnLoad()) { 349 openDispatcher = true; 350 } 351 } 352 openDispatcherWithPanel.setSelected(openDispatcher); 353 openDispatcherWithPanel.setEnabled(!layoutEditorList.isEmpty()); 354 355 optionsFrame.pack(); 356 optionsFrame.setVisible(true); 357 } 358 359 private void applyOptions(ActionEvent e) { 360 dispatcher.setUseConnectivity(useConnectivityCheckBox.isSelected()); 361 dispatcher.setSetSSLDirectionalSensors(setSSLDirectionalSensorsCheckBox.isSelected()); 362 if (trainsFromRoster.isSelected()) { 363 dispatcher.setTrainsFrom(TrainsFrom.TRAINSFROMROSTER); 364 } else if (trainsFromTrains.isSelected()) { 365 dispatcher.setTrainsFrom(TrainsFrom.TRAINSFROMOPS); 366 } else { 367 dispatcher.setTrainsFrom(TrainsFrom.TRAINSFROMUSER); 368 } 369 dispatcher.setHasOccupancyDetection(detectionCheckBox.isSelected()); 370 dispatcher.setAutoAllocate(autoAllocateCheckBox.isSelected()); 371 autoDispatchItem.setSelected(autoAllocateCheckBox.isSelected()); 372 dispatcher.setAutoTurnouts(autoTurnoutsCheckBox.isSelected()); 373 autoTurnoutsItem.setSelected(autoTurnoutsCheckBox.isSelected()); 374 dispatcher.setTrustKnownTurnouts(trustKnownTurnoutsCheckBox.isSelected()); 375 dispatcher.setSignalType(signalTypeBox.getSelectedIndex()); 376 if (autoTurnoutsCheckBox.isSelected() && ((layoutEditorList.size() == 0) 377 || (!useConnectivityCheckBox.isSelected()))) { 378 JmriJOptionPane.showMessageDialog(optionsFrame, Bundle.getMessage( 379 "AutoTurnoutsWarn"), Bundle.getMessage("WarningTitle"), JmriJOptionPane.WARNING_MESSAGE); 380 } 381 dispatcher.setShortActiveTrainNames(shortNameCheckBox.isSelected()); 382 dispatcher.setShortNameInBlock(nameInBlockCheckBox.isSelected()); 383 dispatcher.setExtraColorForAllocated(extraColorForAllocatedCheckBox.isSelected()); 384 dispatcher.setNameInAllocatedBlock(nameInAllocatedBlockCheckBox.isSelected()); 385 dispatcher.setRosterEntryInBlock(rosterInBlockCheckBox.isSelected()); 386 dispatcher.setSupportVSDecoder(supportVSDecoderCheckBox.isSelected()); 387 dispatcher.setScale((Scale) layoutScaleBox.getSelectedItem()); 388 dispatcher.setUseScaleMeters(scaleMeters.isSelected()); 389 dispatcher.setMinThrottleInterval((int) minThrottleIntervalSpinner.getValue()); 390 dispatcher.setFullRampTime((int) fullRampTimeSpinner.getValue()); 391 392 for (LayoutEditor panel : layoutEditorList) { 393 panel.setOpenDispatcherOnLoad(openDispatcherWithPanel.isSelected()); 394 } 395 396 dispatcher.setStoppingSpeedName( (String) stoppingSpeedBox.getSelectedItem()); 397 optionsFrame.setVisible(false); 398 optionsFrame.dispose(); // prevent this window from being listed in the Window menu. 399 optionsFrame = null; 400 // display save options reminder 401 InstanceManager.getDefault(jmri.UserPreferencesManager.class). 402 showInfoMessage(Bundle.getMessage("ReminderTitle"), Bundle.getMessage("ReminderSaveOptions"), 403 OptionsMenu.class.getName(), 404 "remindSaveDispatcherOptions"); // NOI18N 405 initializeMenu(); 406 } 407 408 private void cancelOptions(ActionEvent e) { 409 optionsFrame.setVisible(false); 410 optionsFrame.dispose(); // prevent this window from being listed in the Window menu. 411 optionsFrame = null; 412 } 413 414 /** 415 * Save Dispatcher Option settings from pane to xml file. 416 * 417 * @param e the calling actionevent 418 */ 419 private void saveRequested(ActionEvent e) { 420 try { 421 InstanceManager.getDefault(OptionsFile.class).writeDispatcherOptions(dispatcher); 422 } catch (java.io.IOException ioe) { 423 log.error("Exception writing Dispatcher options", ioe); 424 } 425 } 426 427 private void initializeLayoutEditorList() { 428 // get list of Layout Editor panels 429 layoutEditorList = new ArrayList<>(InstanceManager.getDefault(EditorManager.class).getAll(LayoutEditor.class)); 430 } 431 432 private void initializeScaleCombo() { 433 layoutScaleBox.removeAllItems(); 434 for (Scale scale : ScaleManager.getScales()) { 435 if (scale.getScaleName().equals("CUSTOM")) { // No custom support yet, don't show. 436 continue; 437 } 438 layoutScaleBox.addItem(scale); 439 } 440 jmri.util.swing.JComboBoxUtil.setupComboBoxMaxRows(layoutScaleBox); 441 layoutScaleBox.setSelectedItem(dispatcher.getScale()); 442 } 443 444 private void initializeStoppingSpeedCombo() { 445 stoppingSpeedBox.removeAllItems(); 446 Enumeration<String> speedNamesList = jmri.InstanceManager.getDefault(SignalSpeedMap.class).getSpeedIterator(); 447 while (speedNamesList.hasMoreElements()) { 448 stoppingSpeedBox.addItem(speedNamesList.nextElement()); 449 } 450 stoppingSpeedBox.setSelectedItem(dispatcher.getStoppingSpeedName()); 451 } 452 453 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(OptionsMenu.class); 454 455}