001package jmri.jmrit.display.layoutEditor; 002 003import java.awt.BorderLayout; 004import java.awt.Color; 005import java.awt.Component; 006import java.awt.Container; 007import java.awt.FlowLayout; 008import java.awt.GridLayout; 009import java.awt.Point; 010import java.awt.event.ActionEvent; 011import java.awt.event.WindowAdapter; 012import java.awt.event.WindowEvent; 013import java.awt.geom.Point2D; 014 015import java.util.*; 016import javax.annotation.*; 017import javax.swing.*; 018import javax.swing.border.Border; 019 020import jmri.*; 021import jmri.NamedBean.DisplayOptions; 022import jmri.implementation.DefaultConditionalAction; 023import jmri.jmrit.blockboss.BlockBossLogic; 024import jmri.jmrit.blockboss.BlockBossLogicProvider; 025import jmri.jmrit.catalog.NamedIcon; 026import jmri.jmrit.display.*; 027import jmri.jmrit.signalling.SignallingGuiTools; 028import jmri.swing.NamedBeanComboBox; 029import jmri.util.JmriJFrame; 030import jmri.util.MathUtil; 031import jmri.util.swing.JComboBoxUtil; 032import jmri.util.swing.JmriJOptionPane; 033 034/** 035 * Layout Editor Tools provides tools making use of layout connectivity 036 * available in Layout Editor panels. 037 * <p> 038 * The tools in this module are accessed via the Tools menu in Layout Editor. 039 * 040 * @author Dave Duchamp Copyright (c) 2007 041 * @author George Warner Copyright (c) 2017-2019 042 */ 043final public class LayoutEditorTools { 044 045 //constants 046 //private final int NONE = 0; //Signal at Turnout Positions 047 //operational instance variables shared between tools 048 private LayoutEditor layoutEditor = null; 049 private MultiIconEditor signalIconEditor = null; 050 private JFrame signalFrame = null; 051 private boolean needRedraw = false; 052 private BlockBossLogic logic = null; 053 private SignalHead auxSignal = null; 054 055 //constructor method 056 public LayoutEditorTools(@Nonnull LayoutEditor thePanel) { 057 layoutEditor = thePanel; 058 059 //Turnouts 060 LayoutEditor.setupComboBox(sensorsTurnoutComboBox, true, true, false); 061 LayoutEditor.setupComboBox(signalMastsTurnoutComboBox, true, true, false); 062 LayoutEditor.setupComboBox(turnout1ComboBox, true, true, false); 063 LayoutEditor.setupComboBox(turnout2ComboBox, true, true, false); 064 LayoutEditor.setupComboBox(turnoutAComboBox, true, true, false); 065 LayoutEditor.setupComboBox(turnoutBComboBox, true, true, false); 066 LayoutEditor.setupComboBox(turnoutComboBox, true, true, false); 067 068 //Blocks 069 LayoutEditor.setupComboBox(block1IDComboBox, true, true, false); 070 LayoutEditor.setupComboBox(block2IDComboBox, true, true, false); 071 LayoutEditor.setupComboBox(blockACComboBox, true, true, false); 072 LayoutEditor.setupComboBox(blockBDComboBox, true, true, false); 073 LayoutEditor.setupComboBox(slipSensorsBlockAComboBox, true, true, false); 074 LayoutEditor.setupComboBox(slipSensorsBlockBComboBox, true, true, false); 075 LayoutEditor.setupComboBox(slipSensorsBlockCComboBox, true, true, false); 076 LayoutEditor.setupComboBox(slipSensorsBlockDComboBox, true, true, false); 077 LayoutEditor.setupComboBox(slipSignalBlockAComboBox, true, true, false); 078 LayoutEditor.setupComboBox(slipSignalBlockBComboBox, true, true, false); 079 LayoutEditor.setupComboBox(slipSignalBlockCComboBox, true, true, false); 080 LayoutEditor.setupComboBox(slipSignalBlockDComboBox, true, true, false); 081 LayoutEditor.setupComboBox(xingBlockACComboBox, true, true, false); 082 LayoutEditor.setupComboBox(xingBlockBDComboBox, true, true, false); 083 LayoutEditor.setupComboBox(xingSensorsBlockACComboBox, true, true, false); 084 LayoutEditor.setupComboBox(xingSensorsBlockBDComboBox, true, true, false); 085 086 //Signal Heads 087 LayoutEditor.setupComboBox(a1_3WaySignalHeadComboBox, true, true, false); 088 LayoutEditor.setupComboBox(a1SignalHeadComboBox, true, true, false); 089 LayoutEditor.setupComboBox(a1SlipSignalHeadComboBox, true, true, false); 090 LayoutEditor.setupComboBox(a1TToTSignalHeadComboBox, true, true, false); 091 LayoutEditor.setupComboBox(a2_3WaySignalHeadComboBox, true, true, false); 092 LayoutEditor.setupComboBox(a2SignalHeadComboBox, true, true, false); 093 LayoutEditor.setupComboBox(a2SlipSignalHeadComboBox, true, true, false); 094 LayoutEditor.setupComboBox(a2TToTSignalHeadComboBox, true, true, false); 095 LayoutEditor.setupComboBox(a3_3WaySignalHeadComboBox, true, true, false); 096 LayoutEditor.setupComboBox(aSignalHeadComboBox, true, true, false); 097 LayoutEditor.setupComboBox(b_3WaySignalHeadComboBox, true, true, false); 098 LayoutEditor.setupComboBox(b1SignalHeadComboBox, true, true, false); 099 LayoutEditor.setupComboBox(b1SlipSignalHeadComboBox, true, true, false); 100 LayoutEditor.setupComboBox(b1TToTSignalHeadComboBox, true, true, false); 101 LayoutEditor.setupComboBox(b2SignalHeadComboBox, true, true, false); 102 LayoutEditor.setupComboBox(b2SlipSignalHeadComboBox, true, true, false); 103 LayoutEditor.setupComboBox(b2TToTSignalHeadComboBox, true, true, false); 104 LayoutEditor.setupComboBox(bSignalHeadComboBox, true, true, false); 105 LayoutEditor.setupComboBox(c_3WaySignalHeadComboBox, true, true, false); 106 LayoutEditor.setupComboBox(c1SignalHeadComboBox, true, true, false); 107 LayoutEditor.setupComboBox(c1SlipSignalHeadComboBox, true, true, false); 108 LayoutEditor.setupComboBox(c1TToTSignalHeadComboBox, true, true, false); 109 LayoutEditor.setupComboBox(c2SignalHeadComboBox, true, true, false); 110 LayoutEditor.setupComboBox(c2SlipSignalHeadComboBox, true, true, false); 111 LayoutEditor.setupComboBox(c2TToTSignalHeadComboBox, true, true, false); 112 LayoutEditor.setupComboBox(continuingSignalHeadComboBox, false, true, false); 113 LayoutEditor.setupComboBox(cSignalHeadComboBox, true, true, false); 114 LayoutEditor.setupComboBox(d_3WaySignalHeadComboBox, true, true, false); 115 LayoutEditor.setupComboBox(d1SignalHeadComboBox, true, true, false); 116 LayoutEditor.setupComboBox(d1SlipSignalHeadComboBox, true, true, false); 117 LayoutEditor.setupComboBox(d1TToTSignalHeadComboBox, true, true, false); 118 LayoutEditor.setupComboBox(d2SignalHeadComboBox, true, true, false); 119 LayoutEditor.setupComboBox(d2SlipSignalHeadComboBox, true, true, false); 120 LayoutEditor.setupComboBox(d2TToTSignalHeadComboBox, true, true, false); 121 LayoutEditor.setupComboBox(divergingSignalHeadComboBox, false, true, false); 122 LayoutEditor.setupComboBox(dSignalHeadComboBox, true, true, false); 123 LayoutEditor.setupComboBox(eastBoundSignalHeadComboBox, true, true, false); 124 LayoutEditor.setupComboBox(throatContinuingSignalHeadComboBox, false, true, false); 125 LayoutEditor.setupComboBox(throatDivergingSignalHeadComboBox, false, true, false); 126 LayoutEditor.setupComboBox(westBoundSignalHeadComboBox, true, true, false); 127 128 // TODO: Set combobox exclude lists for turnouts, blocks and signal heads 129 // that are not part of the current layout panel 130 } 131 132 /*=====================*\ 133 |* setSignalsAtTurnout *| 134 \*=====================*/ 135 /** 136 * Tool to set signals at a turnout, including placing the signal icons and 137 * optionally setup of Simple Signal Logic for each signal head 138 * <p> 139 * This tool assumes left facing signal head icons have been selected, and 140 * will rotate the signal head icons accordingly. 141 * <p> 142 * This tool will place throat icons on the right side of the track, and 143 * continuing and diverging icons on the outside edge of the turnout. 144 */ 145 //operational variables for Set Signals at Turnout tool 146 private JmriJFrame setSignalsAtTurnoutFrame = null; 147 private boolean setSignalsAtTurnoutOpenFlag = false; 148 private boolean setSignalsAtTurnoutFromMenuFlag = false; 149 150 private JLabel turnoutNameLabel = null; 151 152 private final NamedBeanComboBox<Turnout> turnoutComboBox = new NamedBeanComboBox<>( 153 InstanceManager.turnoutManagerInstance(), 154 null, DisplayOptions.DISPLAYNAME); 155 156 private final NamedBeanComboBox<SignalHead> throatContinuingSignalHeadComboBox = new NamedBeanComboBox<>( 157 InstanceManager.getDefault(SignalHeadManager.class), 158 null, DisplayOptions.DISPLAYNAME); 159 private final NamedBeanComboBox<SignalHead> throatDivergingSignalHeadComboBox = new NamedBeanComboBox<>( 160 InstanceManager.getDefault(SignalHeadManager.class), 161 null, DisplayOptions.DISPLAYNAME); 162 private final NamedBeanComboBox<SignalHead> continuingSignalHeadComboBox = new NamedBeanComboBox<>( 163 InstanceManager.getDefault(SignalHeadManager.class), 164 null, DisplayOptions.DISPLAYNAME); 165 private final NamedBeanComboBox<SignalHead> divergingSignalHeadComboBox = new NamedBeanComboBox<>( 166 InstanceManager.getDefault(SignalHeadManager.class), 167 null, DisplayOptions.DISPLAYNAME); 168 169 private final JCheckBox setPlaceAllHeads = new JCheckBox(Bundle.getMessage("PlaceAllHeads")); 170 private final JCheckBox setupAllLogic = new JCheckBox(Bundle.getMessage("SetAllLogic")); 171 172 private final JCheckBox setThroatContinuing = new JCheckBox(Bundle.getMessage("PlaceHead")); 173 private final JCheckBox setupLogicThroatContinuing = new JCheckBox(Bundle.getMessage("SetLogic")); 174 private final JCheckBox setThroatDiverging = new JCheckBox(Bundle.getMessage("PlaceHead")); 175 private final JCheckBox setupLogicThroatDiverging = new JCheckBox(Bundle.getMessage("SetLogic")); 176 private final JCheckBox setContinuing = new JCheckBox(Bundle.getMessage("PlaceHead")); 177 private final JCheckBox setupLogicContinuing = new JCheckBox(Bundle.getMessage("SetLogic")); 178 private final JCheckBox setDiverging = new JCheckBox(Bundle.getMessage("PlaceHead")); 179 private final JCheckBox setupLogicDiverging = new JCheckBox(Bundle.getMessage("SetLogic")); 180 private JButton getSavedSignalHeads = null; 181 private JButton changeSignalIcon = null; 182 private JButton setSignalsDone = null; 183 private JButton setSignalsCancel = null; 184 185 private LayoutTurnout layoutTurnout = null; 186 private double placeSignalDirectionDEG = 0.0; 187 188 private Turnout turnout = null; 189 private SignalHead throatContinuingHead = null; 190 private SignalHead throatDivergingHead = null; 191 private SignalHead continuingHead = null; 192 private SignalHead divergingHead = null; 193 194 //display dialog for Set Signals at Turnout tool 195 public void setSignalsAtTurnoutFromMenu(@Nonnull LayoutTurnout to, 196 @Nonnull MultiIconEditor theEditor, @Nonnull JFrame theFrame) { 197 layoutTurnout = to; 198 turnout = to.getTurnout(); 199 turnoutComboBox.setSelectedItem(to.getTurnout()); 200 setSignalsAtTurnoutFromMenuFlag = true; 201 setSignalsAtTurnout(theEditor, theFrame); 202 setSignalsAtTurnoutFromMenuFlag = false; 203 } 204 205 public void setSignalsAtTurnout(@Nonnull MultiIconEditor theEditor, 206 @Nonnull JFrame theFrame) { 207 signalIconEditor = theEditor; 208 signalFrame = theFrame; 209 210 //Initialize if needed 211 if (setSignalsAtTurnoutFrame == null) { 212 setSignalsAtTurnoutOpenFlag = false; 213 setSignalsAtTurnoutFrame = new JmriJFrame(Bundle.getMessage("SignalsAtTurnout"), false, true); 214 oneFrameToRuleThemAll(setSignalsAtTurnoutFrame); 215 setSignalsAtTurnoutFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 216 217 setSignalsAtTurnoutFrame.addHelpMenu("package.jmri.jmrit.display.SetSignalsAtTurnout", true); 218 setSignalsAtTurnoutFrame.setLocation(70, 30); 219 Container theContentPane = setSignalsAtTurnoutFrame.getContentPane(); 220 theContentPane.setLayout(new BoxLayout(theContentPane, BoxLayout.Y_AXIS)); 221 222 JPanel panel1 = new JPanel(new FlowLayout()); 223 turnoutNameLabel = new JLabel(Bundle.getMessage("MakeLabel", Bundle.getMessage("BeanNameTurnout"))); 224 panel1.add(turnoutNameLabel); 225 panel1.add(turnoutComboBox); 226 turnoutNameLabel.setLabelFor(turnoutComboBox); 227 turnoutComboBox.setToolTipText(Bundle.getMessage("SignalsTurnoutNameHint")); 228 theContentPane.add(panel1); 229 theContentPane.add(new JSeparator(JSeparator.HORIZONTAL)); 230 231 JPanel panel2 = new JPanel(new FlowLayout()); 232 JLabel shTitle = new JLabel(Bundle.getMessage("SignalHeads")); 233 panel2.add(shTitle); 234 panel2.add(new JLabel(" ")); 235 panel2.add(getSavedSignalHeads = new JButton(Bundle.getMessage("GetSaved"))); 236 getSavedSignalHeads.addActionListener(this::turnoutSignalsGetSaved); 237 getSavedSignalHeads.setToolTipText(Bundle.getMessage("GetSavedHint")); 238 theContentPane.add(panel2); 239 240 theContentPane.add(new JSeparator(JSeparator.HORIZONTAL)); 241 JPanel panel2a = new JPanel(new FlowLayout()); 242 panel2a.add(new JLabel(" ")); 243 panel2a.add(setPlaceAllHeads); 244 setPlaceAllHeads.setToolTipText(Bundle.getMessage("PlaceAllHeadsHint")); 245 setPlaceAllHeads.addActionListener((ActionEvent e) -> { 246 boolean isSelected = setPlaceAllHeads.isSelected(); 247 //(de)select all checkboxes 248 setThroatContinuing.setSelected(isSelected); 249 setThroatDiverging.setSelected(isSelected); 250 setContinuing.setSelected(isSelected); 251 setDiverging.setSelected(isSelected); 252 }); 253 panel2a.add(new JLabel(" ")); 254 panel2a.add(setupAllLogic); 255 setupAllLogic.setToolTipText(Bundle.getMessage("SetAllLogicHint")); 256 setupAllLogic.addActionListener((ActionEvent e) -> { 257 boolean isSelected = setupAllLogic.isSelected(); 258 //(de)select all checkboxes 259 setupLogicThroatContinuing.setSelected(isSelected); 260 setupLogicThroatDiverging.setSelected(isSelected); 261 setupLogicContinuing.setSelected(isSelected); 262 setupLogicDiverging.setSelected(isSelected); 263 }); 264 theContentPane.add(panel2a); 265 266 JPanel panel21 = new JPanel(new FlowLayout()); 267 JLabel throatContinuingLabel = new JLabel( 268 Bundle.getMessage("MakeLabel", throatContinuingString)); 269 panel21.add(throatContinuingLabel); 270 panel21.add(throatContinuingSignalHeadComboBox); 271 throatContinuingLabel.setLabelFor(throatContinuingSignalHeadComboBox); 272 theContentPane.add(panel21); 273 throatContinuingSignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 274 275 JPanel panel22 = new JPanel(new FlowLayout()); 276 panel22.add(new JLabel(" ")); 277 panel22.add(setThroatContinuing); 278 setThroatContinuing.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 279 panel22.add(new JLabel(" ")); 280 panel22.add(setupLogicThroatContinuing); 281 setupLogicThroatContinuing.setToolTipText(Bundle.getMessage("SetLogicHint")); 282 theContentPane.add(panel22); 283 284 JPanel panel31 = new JPanel(new FlowLayout()); 285 JLabel throatDivergingLabel = new JLabel( 286 Bundle.getMessage("MakeLabel", throatDivergingString)); 287 panel31.add(throatDivergingLabel); 288 panel31.add(throatDivergingSignalHeadComboBox); 289 throatDivergingLabel.setLabelFor(throatDivergingSignalHeadComboBox); 290 theContentPane.add(panel31); 291 throatDivergingSignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 292 293 JPanel panel32 = new JPanel(new FlowLayout()); 294 panel32.add(new JLabel(" ")); 295 panel32.add(setThroatDiverging); 296 setThroatDiverging.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 297 panel32.add(new JLabel(" ")); 298 panel32.add(setupLogicThroatDiverging); 299 setupLogicThroatDiverging.setToolTipText(Bundle.getMessage("SetLogicHint")); 300 theContentPane.add(panel32); 301 302 JPanel panel41 = new JPanel(new FlowLayout()); 303 JLabel continuingLabel = new JLabel( 304 Bundle.getMessage("MakeLabel", continuingString)); 305 panel41.add(continuingLabel); 306 panel41.add(continuingSignalHeadComboBox); 307 continuingLabel.setLabelFor(continuingSignalHeadComboBox); 308 theContentPane.add(panel41); 309 continuingSignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 310 311 JPanel panel42 = new JPanel(new FlowLayout()); 312 panel42.add(new JLabel(" ")); 313 panel42.add(setContinuing); 314 setContinuing.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 315 panel42.add(new JLabel(" ")); 316 panel42.add(setupLogicContinuing); 317 setupLogicContinuing.setToolTipText(Bundle.getMessage("SetLogicHint")); 318 theContentPane.add(panel42); 319 320 JPanel panel51 = new JPanel(new FlowLayout()); 321 JLabel divergingLabel = new JLabel( 322 Bundle.getMessage("MakeLabel", divergingString)); 323 panel51.add(divergingLabel); 324 panel51.add(divergingSignalHeadComboBox); 325 divergingLabel.setLabelFor(divergingSignalHeadComboBox); 326 theContentPane.add(panel51); 327 divergingSignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 328 329 JPanel panel52 = new JPanel(new FlowLayout()); 330 panel52.add(new JLabel(" ")); 331 panel52.add(setDiverging); 332 setDiverging.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 333 panel52.add(new JLabel(" ")); 334 panel52.add(setupLogicDiverging); 335 setupLogicDiverging.setToolTipText(Bundle.getMessage("SetLogicHint")); 336 theContentPane.add(panel52); 337 theContentPane.add(new JSeparator(JSeparator.HORIZONTAL)); 338 339 JPanel panel6 = new JPanel(new FlowLayout()); 340 panel6.add(changeSignalIcon = new JButton(Bundle.getMessage("ChangeSignalIcon"))); 341 changeSignalIcon.addActionListener((ActionEvent e) -> signalFrame.setVisible(true)); 342 changeSignalIcon.setToolTipText(Bundle.getMessage("ChangeSignalIconHint")); 343 panel6.add(new JLabel(" ")); 344 panel6.add(setSignalsDone = new JButton(Bundle.getMessage("ButtonDone"))); 345 setSignalsDone.addActionListener(this::setSignalsDonePressed); 346 setSignalsDone.setToolTipText(Bundle.getMessage("DoneHint", Bundle.getMessage("ButtonDone"))); 347 348 panel6.add(setSignalsCancel = new JButton(Bundle.getMessage("ButtonCancel"))); 349 setSignalsCancel.addActionListener(this::setSignalsCancelPressed); 350 setSignalsCancel.setToolTipText(Bundle.getMessage("CancelHint", Bundle.getMessage("ButtonCancel"))); 351 theContentPane.add(panel6); 352 setSignalsAtTurnoutFrame.addWindowListener(new WindowAdapter() { 353 @Override 354 public void windowClosing(WindowEvent e) { 355 setSignalsCancelPressed(null); 356 } 357 }); 358 } 359 setPlaceAllHeads.setSelected(false); 360 setupAllLogic.setSelected(false); 361 362 turnoutComboBox.setVisible(!setSignalsAtTurnoutFromMenuFlag); 363 String turnoutLabelString = Bundle.getMessage("MakeLabel", Bundle.getMessage("BeanNameTurnout")); 364 if (setSignalsAtTurnoutFromMenuFlag) { 365 turnoutNameLabel.setText(turnoutLabelString + layoutTurnout.getTurnoutName()); 366 turnoutSignalsGetSaved(null); 367 } else { 368 turnoutNameLabel.setText(turnoutLabelString); 369 } 370 371 if (!setSignalsAtTurnoutOpenFlag) { 372 setSignalsAtTurnoutFrame.setPreferredSize(null); 373 setSignalsAtTurnoutFrame.pack(); 374 setSignalsAtTurnoutOpenFlag = true; 375 } 376 setSignalsAtTurnoutFrame.setVisible(true); 377 } //setSignalsAtTurnout 378 379 private void turnoutSignalsGetSaved(ActionEvent a) { 380 if (getTurnoutInformation(false)) { 381 throatContinuingSignalHeadComboBox.setSelectedItem(layoutTurnout.getSignalA1()); 382 throatDivergingSignalHeadComboBox.setSelectedItem(layoutTurnout.getSignalA2()); 383 continuingSignalHeadComboBox.setSelectedItem(layoutTurnout.getSignalB1()); 384 divergingSignalHeadComboBox.setSelectedItem(layoutTurnout.getSignalC1()); 385 } 386 } 387 388 private void setSignalsCancelPressed(ActionEvent a) { 389 setSignalsAtTurnoutOpenFlag = false; 390 setSignalsAtTurnoutFrame.setVisible(false); 391 } 392 393 private void setSignalsDonePressed(ActionEvent a) { 394 //process turnout name 395 if (!getTurnoutInformation(false)) { 396 return; 397 } 398 //process signal head names 399 if (!getTurnoutSignalHeadInformation()) { 400 return; 401 } 402 //place signals as requested 403 String signalHeadName = throatContinuingSignalHeadComboBox.getSelectedItemDisplayName(); 404 if (signalHeadName == null) { 405 signalHeadName = ""; 406 } 407 if (setThroatContinuing.isSelected()) { 408 if (isHeadOnPanel(throatContinuingHead) 409 && (throatContinuingHead != getHeadFromName(layoutTurnout.getSignalA1Name()))) { 410 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 411 Bundle.getMessage("SignalsError6", 412 new Object[]{signalHeadName}), 413 Bundle.getMessage("ErrorTitle"), 414 JmriJOptionPane.ERROR_MESSAGE); 415 return; 416 } else { 417 removeSignalHeadFromPanel(layoutTurnout.getSignalA1Name()); 418 placeThroatContinuing(); 419 removeAssignment(throatContinuingHead); 420 layoutTurnout.setSignalA1Name(signalHeadName); 421 needRedraw = true; 422 } 423 } else { 424 LayoutTurnout.Geometry assigned = isHeadAssignedHere(throatContinuingHead, layoutTurnout); 425 if (assigned == LayoutTurnout.Geometry.NONE) { 426 if (isHeadOnPanel(throatContinuingHead) 427 && isHeadAssignedAnywhere(throatContinuingHead)) { 428 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 429 Bundle.getMessage("SignalsError8", 430 new Object[]{signalHeadName}), 431 Bundle.getMessage("ErrorTitle"), 432 JmriJOptionPane.ERROR_MESSAGE); 433 return; 434 } else { 435 removeSignalHeadFromPanel(layoutTurnout.getSignalA1Name()); 436 removeAssignment(throatContinuingHead); 437 layoutTurnout.setSignalA1Name(signalHeadName); 438 } 439 //} else if (assigned != A1) { 440 //TODO: need to figure out what to do in this case 441 //assigned to a different position on the same turnout. 442 //} 443 } 444 } 445 signalHeadName = throatDivergingSignalHeadComboBox.getSelectedItemDisplayName(); 446 if (signalHeadName == null) { 447 signalHeadName = ""; 448 } 449 if ((setThroatDiverging.isSelected()) && (throatDivergingHead != null)) { 450 if (isHeadOnPanel(throatDivergingHead) 451 && (throatDivergingHead != getHeadFromName(layoutTurnout.getSignalA2Name()))) { 452 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 453 Bundle.getMessage("SignalsError6", 454 new Object[]{signalHeadName}), 455 Bundle.getMessage("ErrorTitle"), 456 JmriJOptionPane.ERROR_MESSAGE); 457 return; 458 } else { 459 removeSignalHeadFromPanel(layoutTurnout.getSignalA2Name()); 460 placeThroatDiverging(); 461 removeAssignment(throatDivergingHead); 462 layoutTurnout.setSignalA2Name(signalHeadName); 463 needRedraw = true; 464 } 465 } else if (throatDivergingHead != null) { 466 LayoutTurnout.Geometry assigned = isHeadAssignedHere(throatDivergingHead, layoutTurnout); 467 if (assigned == LayoutTurnout.Geometry.NONE) { 468 if (isHeadOnPanel(throatDivergingHead) 469 && isHeadAssignedAnywhere(throatDivergingHead)) { 470 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 471 Bundle.getMessage("SignalsError8", 472 new Object[]{signalHeadName}), 473 Bundle.getMessage("ErrorTitle"), 474 JmriJOptionPane.ERROR_MESSAGE); 475 return; 476 } else { 477 removeSignalHeadFromPanel(layoutTurnout.getSignalA2Name()); 478 removeAssignment(throatDivergingHead); 479 layoutTurnout.setSignalA2Name(signalHeadName); 480 } 481 //} else if (assigned != A2) { 482 //need to figure out what to do in this case - assigned to a different position on the same turnout. 483 } 484 } else { //throatDivergingHead is always null here 485 removeSignalHeadFromPanel(layoutTurnout.getSignalA2Name()); 486 layoutTurnout.setSignalA2Name(""); 487 } 488 489 signalHeadName = continuingSignalHeadComboBox.getSelectedItemDisplayName(); 490 if (signalHeadName == null) { 491 signalHeadName = ""; 492 } 493 if (setContinuing.isSelected()) { 494 if (isHeadOnPanel(continuingHead) 495 && (continuingHead != getHeadFromName(layoutTurnout.getSignalB1Name()))) { 496 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 497 Bundle.getMessage("SignalsError6", 498 new Object[]{signalHeadName}), 499 Bundle.getMessage("ErrorTitle"), 500 JmriJOptionPane.ERROR_MESSAGE); 501 return; 502 } else { 503 removeSignalHeadFromPanel(layoutTurnout.getSignalB1Name()); 504 if (layoutTurnout.getContinuingSense() == Turnout.CLOSED) { 505 placeContinuing(signalHeadName); 506 } else { 507 placeDiverging(signalHeadName); 508 } 509 removeAssignment(continuingHead); 510 layoutTurnout.setSignalB1Name(signalHeadName); 511 needRedraw = true; 512 } 513 } else { 514 LayoutTurnout.Geometry assigned = isHeadAssignedHere(continuingHead, layoutTurnout); 515 if (assigned == LayoutTurnout.Geometry.NONE) { 516 if (isHeadOnPanel(continuingHead) 517 && isHeadAssignedAnywhere(continuingHead)) { 518 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 519 Bundle.getMessage("SignalsError8", 520 new Object[]{signalHeadName}), 521 Bundle.getMessage("ErrorTitle"), 522 JmriJOptionPane.ERROR_MESSAGE); 523 return; 524 } else { 525 removeSignalHeadFromPanel(layoutTurnout.getSignalB1Name()); 526 removeAssignment(continuingHead); 527 layoutTurnout.setSignalB1Name(signalHeadName); 528 } 529 //} else if (assigned != B1) { 530 //need to figure out what to do in this case - assigned to a different position on the same turnout. 531 } 532 } 533 534 signalHeadName = divergingSignalHeadComboBox.getSelectedItemDisplayName(); 535 if (signalHeadName == null) { 536 signalHeadName = ""; 537 } 538 if (setDiverging.isSelected()) { 539 if (isHeadOnPanel(divergingHead) 540 && (divergingHead != getHeadFromName(layoutTurnout.getSignalC1Name()))) { 541 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 542 Bundle.getMessage("SignalsError6", 543 new Object[]{signalHeadName}), 544 Bundle.getMessage("ErrorTitle"), 545 JmriJOptionPane.ERROR_MESSAGE); 546 return; 547 } else { 548 removeSignalHeadFromPanel(layoutTurnout.getSignalC1Name()); 549 if (layoutTurnout.getContinuingSense() == Turnout.CLOSED) { 550 placeDiverging(signalHeadName); 551 } else { 552 placeContinuing(signalHeadName); 553 } 554 removeAssignment(divergingHead); 555 layoutTurnout.setSignalC1Name(signalHeadName); 556 needRedraw = true; 557 } 558 } else { 559 LayoutTurnout.Geometry assigned = isHeadAssignedHere(divergingHead, layoutTurnout); 560 if (assigned == LayoutTurnout.Geometry.NONE) { 561 if (isHeadOnPanel(divergingHead) 562 && isHeadAssignedAnywhere(divergingHead)) { 563 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 564 Bundle.getMessage("SignalsError8", 565 new Object[]{signalHeadName}), 566 Bundle.getMessage("ErrorTitle"), 567 JmriJOptionPane.ERROR_MESSAGE); 568 return; 569 } else { 570 removeSignalHeadFromPanel(layoutTurnout.getSignalC1Name()); 571 removeAssignment(divergingHead); 572 layoutTurnout.setSignalC1Name(signalHeadName); 573 } 574 //} else if (assigned != C1) { 575 //need to figure out what to do in this case - assigned to a different position on the same turnout. 576 } 577 } 578 //setup Logic if requested and enough information is available 579 if (setupLogicThroatContinuing.isSelected()) { 580 setLogicThroatContinuing(); 581 } 582 if ((throatDivergingHead != null) && setupLogicThroatDiverging.isSelected()) { 583 setLogicThroatDiverging(); 584 } 585 if (setupLogicContinuing.isSelected()) { 586 setLogicContinuing(); 587 } 588 if (setupLogicDiverging.isSelected()) { 589 setLogicDiverging(); 590 } 591 //make sure this layout turnout is not linked to another 592 layoutTurnout.setLinkType(LayoutTurnout.LinkType.NO_LINK); 593 layoutTurnout.setLinkedTurnoutName(""); 594 //finish up 595 setSignalsAtTurnoutOpenFlag = false; 596 setSignalsAtTurnoutFrame.setVisible(false); 597 if (needRedraw) { 598 layoutEditor.redrawPanel(); 599 layoutEditor.setDirty(); 600 needRedraw = false; 601 } 602 } //setSignalsDonePressed 603 604 /** 605 * Checks the turnout name (could also be a crossover, ...) 606 * 1) checks setSignalsAtTurnoutFromMenuFlag (bis setSignalsAtXoverTurnoutFromMenuFlag) 607 * skip to 6 if true 608 * 2) get a name string from turnoutComboBox (bis NamedBean.normalizeUserName(xoverTurnoutName) ), 609 * showing an error dialog if not present 610 * 3) Gets turnout by that name, showing a error and returning false if not 611 * 4) (??) if the turnout's user name is non-existant or not matching, reset the turnout name string source 612 * used in 2 (does this ever work?) 613 * 5) Search through all LayoutTurnout (and subclass) objects, looking for a match. If 614 * is the other type (LayoutTurnout vs XOver or vice-versa), so an error, 615 * call a cancel routine and return false. Save the found item in the 616 * 'layoutTurnout' non-local variable 617 * 618 * 6) If the above succeed in finding a layoutTurnout, calculate an angle and 619 * store in the `placeSignalDirectionDEG` non-local variable 620 * and return true (success) 621 * 7) Finally, show an error saying the turnout is not displayed on this panel and return false. 622 * 623 * In summary, this makes some checks, and then (re)loads the 'layoutTurnout' and 624 * 'placeSignalDirectionDEG' non-local variables, returning true for success 625 * 626 * @return true if ok, false if not for various reasons 627 */ 628 private boolean getTurnoutInformation(boolean isCrossover) { 629 String str = ""; 630 if (isCrossover ? !setSignalsAtXoverTurnoutFromMenuFlag : !setSignalsAtTurnoutFromMenuFlag) { 631 turnout = null; 632 layoutTurnout = null; 633 str = isCrossover ? NamedBean.normalizeUserName(xoverTurnoutName) 634 : turnoutComboBox.getSelectedItemDisplayName(); 635 if ((str == null) || str.isEmpty()) { 636 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 637 Bundle.getMessage("SignalsError1"), 638 Bundle.getMessage("ErrorTitle"), 639 JmriJOptionPane.ERROR_MESSAGE); 640 return false; 641 } 642 turnout = InstanceManager.turnoutManagerInstance().getTurnout(str); 643 if (turnout == null) { 644 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 645 Bundle.getMessage("SignalsError2", 646 new Object[]{str}), Bundle.getMessage("ErrorTitle"), 647 JmriJOptionPane.ERROR_MESSAGE); 648 return false; 649 } else { 650 String uname = turnout.getUserName(); 651 if ((uname == null) || uname.isEmpty() || !uname.equals(str)) { 652 if (isCrossover) { 653 xoverTurnoutName = str; 654 } else { 655 turnoutComboBox.setSelectedItem(turnout); 656 } 657 } 658 } 659 for (LayoutTurnout t : layoutEditor.getLayoutTurnouts()) { 660 if (t.getTurnout() == turnout) { 661 layoutTurnout = t; 662 if (t.isTurnoutTypeXover() != isCrossover) { 663 if (isCrossover) { 664 JmriJOptionPane.showMessageDialog(layoutEditor, 665 Bundle.getMessage("InfoMessage8"), 666 Bundle.getMessage("MessageTitle"), 667 JmriJOptionPane.INFORMATION_MESSAGE); 668 setXoverSignalsCancelPressed(null); 669 } else { 670 JmriJOptionPane.showMessageDialog(layoutEditor, 671 Bundle.getMessage("InfoMessage1"), 672 Bundle.getMessage("MessageTitle"), 673 JmriJOptionPane.INFORMATION_MESSAGE); 674 setSignalsCancelPressed(null); 675 } 676 return false; 677 } 678 break; 679 } 680 } 681 } 682 683 if (layoutTurnout != null) { 684 // convert to view to get angle on screen display 685 LayoutTurnoutView ltv = layoutEditor.getLayoutTurnoutView(layoutTurnout); 686 687 Point2D coordsA = ltv.getCoordsA(), coords2; 688 if (isCrossover) { 689 coords2 = ltv.getCoordsB(); 690 } else { 691 coords2 = ltv.getCoordsCenter(); 692 } 693 placeSignalDirectionDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coords2, coordsA)); 694 return true; 695 } 696 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 697 Bundle.getMessage("SignalsError3", 698 new Object[]{str}), Bundle.getMessage("ErrorTitle"), 699 JmriJOptionPane.ERROR_MESSAGE); 700 return false; 701 } //getTurnoutInformation 702 703 private boolean getTurnoutSignalHeadInformation() { 704 throatContinuingHead = getSignalHeadFromEntry(throatContinuingSignalHeadComboBox, true, setSignalsAtTurnoutFrame); 705 if (throatContinuingHead == null) { 706 return false; 707 } 708 throatDivergingHead = getSignalHeadFromEntry(throatDivergingSignalHeadComboBox, false, setSignalsAtTurnoutFrame); 709 continuingHead = getSignalHeadFromEntry(continuingSignalHeadComboBox, true, setSignalsAtTurnoutFrame); 710 if (continuingHead == null) { 711 return false; 712 } 713 divergingHead = getSignalHeadFromEntry(divergingSignalHeadComboBox, true, setSignalsAtTurnoutFrame); 714 if (divergingHead == null) { 715 return false; 716 } 717 return true; 718 } 719 private NamedIcon testIcon = null; 720 721 private void placeThroatContinuing() { 722 if (testIcon == null) { 723 testIcon = signalIconEditor.getIcon(0); 724 } 725 String signalHeadName = throatContinuingSignalHeadComboBox.getSelectedItemDisplayName(); 726 if (signalHeadName == null) { 727 signalHeadName = ""; 728 } 729 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 730 731 LayoutTurnoutView layoutTurnoutView = layoutEditor.getLayoutTurnoutView(layoutTurnout); 732 733 Point2D coordsA = layoutTurnoutView.getCoordsA(); 734 Point2D delta = new Point2D.Double(+shift, +shift); 735 736 delta = MathUtil.rotateDEG(delta, placeSignalDirectionDEG); 737 Point2D where = MathUtil.add(coordsA, delta); 738 setSignalHeadOnPanel(placeSignalDirectionDEG + 180.0, signalHeadName, where); 739 } 740 741 private void placeThroatDiverging() { 742 if (testIcon == null) { 743 testIcon = signalIconEditor.getIcon(0); 744 } 745 String signalHeadName = throatDivergingSignalHeadComboBox.getSelectedItemDisplayName(); 746 if (signalHeadName == null) { 747 signalHeadName = ""; 748 } 749 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 750 751 LayoutTurnoutView layoutTurnoutView = layoutEditor.getLayoutTurnoutView(layoutTurnout); 752 753 Point2D coordsA = layoutTurnoutView.getCoordsA(); 754 Point2D delta = new Point2D.Double(-shift, +shift); 755 756 delta = MathUtil.rotateDEG(delta, placeSignalDirectionDEG); 757 Point2D where = MathUtil.add(coordsA, delta); 758 setSignalHeadOnPanel(placeSignalDirectionDEG + 180.0, signalHeadName, where); 759 } 760 761 private void placeContinuing(@Nonnull String signalHeadName) { 762 if (testIcon == null) { 763 testIcon = signalIconEditor.getIcon(0); 764 } 765 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 766 767 LayoutTurnoutView layoutTurnoutView = layoutEditor.getLayoutTurnoutView(layoutTurnout); 768 769 Point2D coordsB = layoutTurnoutView.getCoordsB(); 770 Point2D coordsC = layoutTurnoutView.getCoordsC(); 771 Point2D coordsCenter = layoutTurnoutView.getCoordsCenter(); 772 773 double bDirDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsB, coordsCenter)); 774 double cDirDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsC, coordsCenter)); 775 double diffDirDEG = MathUtil.diffAngleDEG(cDirDEG, bDirDEG); 776 double shiftX = 0.0; 777 if (diffDirDEG < 0.0) { 778 shiftX += shift * Math.cos(Math.toRadians(diffDirDEG)); 779 } 780 Point2D delta = new Point2D.Double(shiftX, -shift); 781 782 delta = MathUtil.rotateDEG(delta, bDirDEG); 783 Point2D where = MathUtil.add(coordsB, delta); 784 setSignalHeadOnPanel(bDirDEG, signalHeadName, where); 785 } 786 787 private void placeDiverging(String signalHeadName) { 788 if (testIcon == null) { 789 testIcon = signalIconEditor.getIcon(0); 790 } 791 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 792 793 LayoutTurnoutView layoutTurnoutView = layoutEditor.getLayoutTurnoutView(layoutTurnout); 794 795 Point2D coordsB = layoutTurnoutView.getCoordsB(); 796 Point2D coordsC = layoutTurnoutView.getCoordsC(); 797 Point2D coordsCenter = layoutTurnoutView.getCoordsCenter(); 798 799 double bDirDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsB, coordsCenter)); 800 double cDirDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsC, coordsCenter)); 801 double diffDirDEG = MathUtil.diffAngleDEG(cDirDEG, bDirDEG); 802 double shiftX = 0.0; 803 if (diffDirDEG >= 0.0) { 804 shiftX += shift * Math.cos(Math.toRadians(diffDirDEG)); 805 } 806 Point2D delta = new Point2D.Double(shiftX, -shift); 807 808 delta = MathUtil.rotateDEG(delta, cDirDEG); 809 Point2D where = MathUtil.add(coordsC, delta); 810 setSignalHeadOnPanel(cDirDEG, signalHeadName, where); 811 } 812 813 private void setLogicThroatContinuing() { 814 TrackSegment track = null; 815 if (layoutTurnout.getContinuingSense() == Turnout.CLOSED) { 816 track = (TrackSegment) layoutTurnout.getConnectB(); 817 } else { 818 track = (TrackSegment) layoutTurnout.getConnectC(); 819 } 820 if (track == null) { 821 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 822 Bundle.getMessage("InfoMessage7"), 823 Bundle.getMessage("MessageTitle"), 824 JmriJOptionPane.INFORMATION_MESSAGE); 825 return; 826 } 827 LayoutBlock block = track.getLayoutBlock(); 828 if (block == null) { 829 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 830 Bundle.getMessage("InfoMessage6"), 831 Bundle.getMessage("MessageTitle"), 832 JmriJOptionPane.INFORMATION_MESSAGE); 833 return; 834 } 835 Sensor occupancy = block.getOccupancySensor(); 836 if (occupancy == null) { 837 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 838 Bundle.getMessage("InfoMessage4", 839 new Object[]{block.getUserName()}), 840 Bundle.getMessage("MessageTitle"), 841 JmriJOptionPane.INFORMATION_MESSAGE); 842 return; 843 } 844 845 String signalHeadName = throatContinuingSignalHeadComboBox.getSelectedItemDisplayName(); 846 if (signalHeadName == null) { 847 signalHeadName = ""; 848 } 849 SignalHead nextHead = getNextSignalFromObject(track, 850 layoutTurnout, signalHeadName, setSignalsAtTurnoutFrame); 851 if ((nextHead == null) && (!reachedEndBumper())) { 852 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 853 Bundle.getMessage("InfoMessage5", 854 new Object[]{block.getUserName()}), 855 Bundle.getMessage("MessageTitle"), 856 JmriJOptionPane.INFORMATION_MESSAGE); 857 return; 858 } 859 if (throatDivergingHead != null) { 860 if (!initializeBlockBossLogic(signalHeadName)) { 861 return; 862 } 863 logic.setMode(BlockBossLogic.TRAILINGMAIN); 864 logic.setTurnout(turnout.getDisplayName()); 865 logic.setSensor1(occupancy.getDisplayName()); 866 if (nextHead != null) { 867 logic.setWatchedSignal1(nextHead.getDisplayName(), false); 868 } 869 if (auxSignal != null) { 870 logic.setWatchedSignal1Alt(auxSignal.getDisplayName()); 871 } 872 finalizeBlockBossLogic(); 873 return; 874 } 875 SignalHead savedAuxSignal = auxSignal; 876 TrackSegment track2 = null; 877 if (layoutTurnout.getContinuingSense() == Turnout.CLOSED) { 878 track2 = (TrackSegment) layoutTurnout.getConnectC(); 879 } else { 880 track2 = (TrackSegment) layoutTurnout.getConnectB(); 881 } 882 if (track2 == null) { 883 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 884 Bundle.getMessage("InfoMessage7"), 885 Bundle.getMessage("MessageTitle"), 886 JmriJOptionPane.INFORMATION_MESSAGE); 887 return; 888 } 889 LayoutBlock block2 = track2.getLayoutBlock(); 890 if (block2 == null) { 891 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 892 Bundle.getMessage("InfoMessage6"), 893 Bundle.getMessage("MessageTitle"), 894 JmriJOptionPane.INFORMATION_MESSAGE); 895 return; 896 } 897 Sensor occupancy2 = block2.getOccupancySensor(); 898 if (occupancy2 == null) { 899 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 900 Bundle.getMessage("InfoMessage4", 901 new Object[]{block2.getUserName()}), 902 Bundle.getMessage("MessageTitle"), 903 JmriJOptionPane.INFORMATION_MESSAGE); 904 return; 905 } 906 signalHeadName = throatContinuingSignalHeadComboBox.getSelectedItemDisplayName(); 907 if (signalHeadName == null) { 908 signalHeadName = ""; 909 } 910 SignalHead nextHead2 = getNextSignalFromObject(track2, 911 layoutTurnout, signalHeadName, setSignalsAtTurnoutFrame); 912 if ((nextHead2 == null) && (!reachedEndBumper())) { 913 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 914 Bundle.getMessage("InfoMessage5", 915 new Object[]{block2.getUserName()}), 916 Bundle.getMessage("MessageTitle"), 917 JmriJOptionPane.INFORMATION_MESSAGE); 918 return; 919 } 920 if (!initializeBlockBossLogic(signalHeadName)) { 921 return; 922 } 923 logic.setMode(BlockBossLogic.FACING); 924 logic.setTurnout(turnout.getDisplayName()); 925 logic.setWatchedSensor1(occupancy.getDisplayName()); 926 logic.setWatchedSensor2(occupancy2.getDisplayName()); 927 if (nextHead != null) { 928 logic.setWatchedSignal1(nextHead.getDisplayName(), false); 929 } 930 if (savedAuxSignal != null) { 931 logic.setWatchedSignal1Alt(savedAuxSignal.getDisplayName()); 932 } 933 if (nextHead2 != null) { 934 logic.setWatchedSignal2(nextHead2.getDisplayName()); 935 } 936 if (auxSignal != null) { 937 logic.setWatchedSignal2Alt(auxSignal.getDisplayName()); 938 } 939 if (!layoutTurnout.isMainlineC()) { 940 logic.setLimitSpeed2(true); 941 } 942 finalizeBlockBossLogic(); 943 } //setLogicThroatContinuing 944 945 private void setLogicThroatDiverging() { 946 TrackSegment track = null; 947 if (layoutTurnout.getContinuingSense() == Turnout.CLOSED) { 948 track = (TrackSegment) layoutTurnout.getConnectC(); 949 } else { 950 track = (TrackSegment) layoutTurnout.getConnectB(); 951 } 952 if (track == null) { 953 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 954 Bundle.getMessage("InfoMessage7"), 955 Bundle.getMessage("MessageTitle"), 956 JmriJOptionPane.INFORMATION_MESSAGE); 957 return; 958 } 959 LayoutBlock block = track.getLayoutBlock(); 960 if (block == null) { 961 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 962 Bundle.getMessage("InfoMessage6"), 963 Bundle.getMessage("MessageTitle"), 964 JmriJOptionPane.INFORMATION_MESSAGE); 965 return; 966 } 967 Sensor occupancy = block.getOccupancySensor(); 968 if (occupancy == null) { 969 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 970 Bundle.getMessage("InfoMessage4", 971 new Object[]{block.getUserName()}), 972 Bundle.getMessage("MessageTitle"), 973 JmriJOptionPane.INFORMATION_MESSAGE); 974 return; 975 } 976 String signalHeadName = throatDivergingSignalHeadComboBox.getSelectedItemDisplayName(); 977 if (signalHeadName == null) { 978 signalHeadName = ""; 979 } 980 SignalHead nextHead = getNextSignalFromObject(track, 981 layoutTurnout, signalHeadName, setSignalsAtTurnoutFrame); 982 if ((nextHead == null) && (!reachedEndBumper())) { 983 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 984 Bundle.getMessage("InfoMessage5", 985 new Object[]{block.getUserName()}), 986 Bundle.getMessage("MessageTitle"), 987 JmriJOptionPane.INFORMATION_MESSAGE); 988 return; 989 } 990 if (!initializeBlockBossLogic(signalHeadName)) { 991 return; 992 } 993 994 logic.setMode(BlockBossLogic.TRAILINGDIVERGING); 995 logic.setTurnout(turnout.getDisplayName()); 996 logic.setSensor1(occupancy.getDisplayName()); 997 if (nextHead != null) { 998 logic.setWatchedSignal1(nextHead.getDisplayName(), false); 999 } 1000 if (auxSignal != null) { 1001 logic.setWatchedSignal1Alt(auxSignal.getDisplayName()); 1002 } 1003 if (!layoutTurnout.isMainlineC()) { 1004 logic.setLimitSpeed2(true); 1005 } 1006 finalizeBlockBossLogic(); 1007 } //setLogicThroatDiverging 1008 1009 private void setLogicContinuing() { 1010 TrackSegment track = (TrackSegment) layoutTurnout.getConnectA(); 1011 if (track == null) { 1012 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 1013 Bundle.getMessage("InfoMessage7"), 1014 Bundle.getMessage("MessageTitle"), 1015 JmriJOptionPane.INFORMATION_MESSAGE); 1016 return; 1017 } 1018 LayoutBlock block = track.getLayoutBlock(); 1019 if (block == null) { 1020 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 1021 Bundle.getMessage("InfoMessage6"), 1022 Bundle.getMessage("MessageTitle"), 1023 JmriJOptionPane.INFORMATION_MESSAGE); 1024 return; 1025 } 1026 Sensor occupancy = block.getOccupancySensor(); 1027 if (occupancy == null) { 1028 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 1029 Bundle.getMessage("InfoMessage4", 1030 new Object[]{block.getUserName()}), 1031 Bundle.getMessage("MessageTitle"), 1032 JmriJOptionPane.INFORMATION_MESSAGE); 1033 return; 1034 } 1035 String signalHeadName = continuingSignalHeadComboBox.getSelectedItemDisplayName(); 1036 if (signalHeadName == null) { 1037 signalHeadName = ""; 1038 } 1039 SignalHead nextHead = getNextSignalFromObject(track, 1040 layoutTurnout, signalHeadName, setSignalsAtTurnoutFrame); 1041 if ((nextHead == null) && (!reachedEndBumper())) { 1042 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 1043 Bundle.getMessage("InfoMessage5", 1044 new Object[]{block.getUserName()}), 1045 Bundle.getMessage("MessageTitle"), 1046 JmriJOptionPane.INFORMATION_MESSAGE); 1047 return; 1048 } 1049 if (!initializeBlockBossLogic(signalHeadName)) { 1050 return; 1051 } 1052 logic.setMode(BlockBossLogic.TRAILINGMAIN); 1053 logic.setTurnout(turnout.getDisplayName()); 1054 logic.setSensor1(occupancy.getDisplayName()); 1055 if (nextHead != null) { 1056 logic.setWatchedSignal1(nextHead.getDisplayName(), false); 1057 } 1058 if (auxSignal != null) { 1059 logic.setWatchedSignal1Alt(auxSignal.getDisplayName()); 1060 } 1061 finalizeBlockBossLogic(); 1062 } //setLogicContinuing 1063 1064 private void setLogicDiverging() { 1065 TrackSegment track = (TrackSegment) layoutTurnout.getConnectA(); 1066 if (track == null) { 1067 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 1068 Bundle.getMessage("InfoMessage7"), 1069 Bundle.getMessage("MessageTitle"), 1070 JmriJOptionPane.INFORMATION_MESSAGE); 1071 return; 1072 } 1073 LayoutBlock block = track.getLayoutBlock(); 1074 if (block == null) { 1075 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 1076 Bundle.getMessage("InfoMessage6"), 1077 Bundle.getMessage("MessageTitle"), 1078 JmriJOptionPane.INFORMATION_MESSAGE); 1079 return; 1080 } 1081 Sensor occupancy = block.getOccupancySensor(); 1082 if (occupancy == null) { 1083 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 1084 Bundle.getMessage("InfoMessage4", 1085 new Object[]{block.getUserName()}), 1086 Bundle.getMessage("MessageTitle"), 1087 JmriJOptionPane.INFORMATION_MESSAGE); 1088 return; 1089 } 1090 String signalHeadName = divergingSignalHeadComboBox.getSelectedItemDisplayName(); 1091 if (signalHeadName == null) { 1092 signalHeadName = ""; 1093 } 1094 SignalHead nextHead = getNextSignalFromObject(track, 1095 layoutTurnout, signalHeadName, setSignalsAtTurnoutFrame); 1096 if ((nextHead == null) && (!reachedEndBumper())) { 1097 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 1098 Bundle.getMessage("InfoMessage5", 1099 new Object[]{block.getUserName()}), 1100 Bundle.getMessage("MessageTitle"), 1101 JmriJOptionPane.INFORMATION_MESSAGE); 1102 return; 1103 } 1104 if (!initializeBlockBossLogic(signalHeadName)) { 1105 return; 1106 } 1107 logic.setMode(BlockBossLogic.TRAILINGDIVERGING); 1108 logic.setTurnout(turnout.getDisplayName()); 1109 logic.setSensor1(occupancy.getDisplayName()); 1110 if (nextHead != null) { 1111 logic.setWatchedSignal1(nextHead.getDisplayName(), false); 1112 } 1113 if (auxSignal != null) { 1114 logic.setWatchedSignal1Alt(auxSignal.getDisplayName()); 1115 } 1116 if (!layoutTurnout.isMainlineC()) { 1117 logic.setLimitSpeed2(true); 1118 } 1119 finalizeBlockBossLogic(); 1120 } //setLogicDiverging 1121 1122 /*==========================================*\ 1123 | * Utility routines used by multiple tools *| 1124 \*==========================================*/ 1125 /** 1126 * Returns the layout turnout corresponding to a given turnout. 1127 * <p> 1128 * If require 1129 * double crossover is requested, an error message is sent to the user if 1130 * the layout turnout is not a double crossover, and null is returned. 1131 * <p> 1132 * If a layout turnout corresponding to the turnout is not found, an error 1133 * message is sent to the user and null is returned. 1134 * 1135 * @param turnout the base turnout. 1136 * @param requireDoubleXover true to force checking of turnout type. 1137 * @param str error message string. 1138 * @param theFrame main frame. 1139 * @return layout turnout, may be null. 1140 */ 1141 @CheckReturnValue 1142 public LayoutTurnout getLayoutTurnoutFromTurnout( 1143 @Nonnull Turnout turnout, 1144 boolean requireDoubleXover, 1145 @Nonnull String str, 1146 @CheckForNull JFrame theFrame) { 1147 for (LayoutTurnout t : layoutEditor.getLayoutTurnouts()) { 1148 if (t.getTurnout() == turnout) { 1149 //have the layout turnout corresponding to the turnout 1150 if ((t.getTurnoutType() == LayoutTurnout.TurnoutType.DOUBLE_XOVER) 1151 && (!requireDoubleXover)) { 1152 JmriJOptionPane.showMessageDialog(theFrame, 1153 Bundle.getMessage("InfoMessage1"), 1154 Bundle.getMessage("MessageTitle"), 1155 JmriJOptionPane.INFORMATION_MESSAGE); 1156 return null; 1157 } 1158 if (requireDoubleXover && (t.getTurnoutType() != LayoutTurnout.TurnoutType.DOUBLE_XOVER)) { 1159 JmriJOptionPane.showMessageDialog(theFrame, 1160 Bundle.getMessage("InfoMessage8"), 1161 Bundle.getMessage("MessageTitle"), 1162 JmriJOptionPane.INFORMATION_MESSAGE); 1163 return null; 1164 } 1165 return t; 1166 } 1167 } 1168 //layout turnout not found 1169 JmriJOptionPane.showMessageDialog(theFrame, 1170 Bundle.getMessage("SignalsError3", 1171 new Object[]{str}), Bundle.getMessage("ErrorTitle"), 1172 JmriJOptionPane.ERROR_MESSAGE); 1173 return null; 1174 } 1175 1176 /** 1177 * Returns the SignalHead corresponding to an entry field in the specified 1178 * dialog. This also takes care of UpperCase and trimming of leading and 1179 * trailing blanks. If entry is required, and no entry is present, and error 1180 * message is sent. An error message also results if a signal head with the 1181 * entered name is not found in the SignalTable. 1182 * @param signalNameComboBox the combo box with signal name selected. 1183 * @param requireEntry true if mandatory field, else false. 1184 * @param frame the main frame. 1185 * @return signal head, may be null. 1186 */ 1187 @CheckReturnValue 1188 public SignalHead getSignalHeadFromEntry( 1189 @Nonnull NamedBeanComboBox<SignalHead> signalNameComboBox, 1190 boolean requireEntry, 1191 @Nonnull JmriJFrame frame) { 1192 String signalName = signalNameComboBox.getSelectedItemDisplayName(); 1193 SignalHead result = getSignalHeadFromEntry(signalName, requireEntry, frame); 1194 if (result != null) { 1195 String uname = result.getUserName(); 1196 if ((uname == null) || uname.isEmpty() || !uname.equals(signalName)) { 1197 signalNameComboBox.setSelectedItem(result); 1198 } 1199 } 1200 return result; 1201 } 1202 1203 @CheckReturnValue 1204 public SignalHead getSignalHeadFromEntry( 1205 @Nonnull JTextField signalNameTextField, 1206 boolean requireEntry, @Nonnull JmriJFrame frame) { 1207 String signalName = NamedBean.normalizeUserName(signalNameTextField.getText()); 1208 SignalHead result = getSignalHeadFromEntry(signalName, requireEntry, frame); 1209 if (result != null) { 1210 String uname = result.getUserName(); 1211 if ((uname == null) || uname.isEmpty() || !uname.equals(signalName)) { 1212 signalNameTextField.setText(signalName); 1213 } 1214 } 1215 return result; 1216 } 1217 1218 @CheckReturnValue 1219 public SignalHead getSignalHeadFromEntry(@CheckForNull String signalName, 1220 boolean requireEntry, @Nonnull JmriJFrame frame) { 1221 if ((signalName == null) || signalName.isEmpty()) { 1222 if (requireEntry) { 1223 JmriJOptionPane.showMessageDialog(frame, Bundle.getMessage("SignalsError5"), 1224 Bundle.getMessage("ErrorTitle"), 1225 JmriJOptionPane.ERROR_MESSAGE); 1226 } 1227 return null; 1228 } 1229 SignalHead head = InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(signalName); 1230 if (head == null) { 1231 JmriJOptionPane.showMessageDialog(frame, 1232 Bundle.getMessage("SignalsError4", 1233 new Object[]{signalName}), Bundle.getMessage("ErrorTitle"), 1234 JmriJOptionPane.ERROR_MESSAGE); 1235 return null; 1236 } 1237 return (head); 1238 } 1239 1240 /** 1241 * Returns a SignalHead given a name. 1242 * @param str signal head name. 1243 * @return signal head, may be null. 1244 */ 1245 @CheckReturnValue 1246 public SignalHead getHeadFromName(@CheckForNull String str) { 1247 SignalHead result = null; 1248 if ((str != null) && !str.isEmpty()) { 1249 result = InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(str); 1250 } 1251 return result; 1252 } 1253 1254 /** 1255 * Places a signal head icon on the panel after rotation at the designated 1256 * place, with all icons taken care of. 1257 * 1258 * @param directionDEG rotation in degrees. 1259 * @param signalHeadName name of a signal head. 1260 * @param where coordinates for placing signal head on panel. 1261 */ 1262 public void setSignalHeadOnPanel(double directionDEG, 1263 @Nonnull String signalHeadName, 1264 @Nonnull Point2D where) { 1265 setSignalHeadOnPanel(directionDEG, signalHeadName, (int) where.getX(), (int) where.getY()); 1266 } 1267 1268 /** 1269 * Places a signal head icon on the panel after rotation at the designated 1270 * place, with all icons taken care of. 1271 * 1272 * @param directionDEG rotation in degrees. 1273 * @param signalHeadName name of a signal head. 1274 * @param xLoc x coordinate for placing signal head on panel. 1275 * @param yLoc y coordinate for placing signal head on panel. 1276 */ 1277 public void setSignalHeadOnPanel(double directionDEG, @Nonnull String signalHeadName, int xLoc, int yLoc) { 1278 SignalHeadIcon l = getSignalHeadIcon(signalHeadName); 1279 1280 if (directionDEG > 0) { 1281 Iterator<String> e = l.getIconStateNames(); 1282 while (e.hasNext()) { 1283 l.getIcon(e.next()).rotate((int) directionDEG, l); 1284 } 1285 } 1286 1287 l.setLocation(xLoc - (int) (l.maxWidth() / 2.0), yLoc - (int) (l.maxHeight() / 2.0)); 1288 1289 layoutEditor.putSignal(l); 1290 } 1291 1292 /** 1293 * Returns an index if the specified signal head is assigned to the 1294 * LayoutTurnout initialized. Otherwise returns the NONE index. The index 1295 * specifies the turnout position of the signal head according to the code 1296 * listed at the beginning of this module. 1297 */ 1298 private LayoutTurnout.Geometry isHeadAssignedHere(@Nonnull SignalHead head, @Nonnull LayoutTurnout lTurnout) { 1299 LayoutTurnout.Geometry result = LayoutTurnout.Geometry.NONE; 1300 1301 Map<String, LayoutTurnout.Geometry> map = new HashMap<>(); 1302 map.put(lTurnout.getSignalA1Name(), LayoutTurnout.Geometry.POINTA1); 1303 map.put(lTurnout.getSignalA2Name(), LayoutTurnout.Geometry.POINTA2); 1304 map.put(lTurnout.getSignalA3Name(), LayoutTurnout.Geometry.POINTA3); 1305 map.put(lTurnout.getSignalB1Name(), LayoutTurnout.Geometry.POINTB1); 1306 map.put(lTurnout.getSignalB2Name(), LayoutTurnout.Geometry.POINTB2); 1307 map.put(lTurnout.getSignalC1Name(), LayoutTurnout.Geometry.POINTC1); 1308 map.put(lTurnout.getSignalC2Name(), LayoutTurnout.Geometry.POINTC2); 1309 map.put(lTurnout.getSignalD1Name(), LayoutTurnout.Geometry.POINTD1); 1310 map.put(lTurnout.getSignalD2Name(), LayoutTurnout.Geometry.POINTD2); 1311 1312 String sName = head.getSystemName(); 1313 String uName = head.getUserName(); 1314 1315 for (Map.Entry<String, LayoutTurnout.Geometry> entry : map.entrySet()) { 1316 String signalName = entry.getKey(); 1317 1318 if (!signalName.isEmpty() && (signalName.equals(sName) || signalName.equals(uName))) { 1319 result = entry.getValue(); 1320 break; 1321 } 1322 } 1323 1324 return result; 1325 } 1326 1327 /** 1328 * Get if signal head is on the panel. 1329 * @param head the signal head to locate. 1330 * @return true if an icon for the specified SignalHead is on the panel. 1331 */ 1332 public boolean isHeadOnPanel(@Nonnull SignalHead head) { 1333 for (SignalHeadIcon h : layoutEditor.getSignalList()) { 1334 if (h.getSignalHead() == head) { 1335 return true; 1336 } 1337 } 1338 return false; 1339 } 1340 1341 /** 1342 * Returns true if the specified Signal Head is assigned to an object on the 1343 * panel, regardless of whether an icon is displayed or not. 1344 * @param head the signal head to locate. 1345 * @return true if the signal head is attached to a panel object. 1346 */ 1347 public boolean isHeadAssignedAnywhere(@Nonnull SignalHead head) { 1348 String sName = head.getSystemName(); 1349 String uName = head.getUserName(); 1350 1351 for (LayoutTurnout to : layoutEditor.getLayoutTurnouts()) { 1352 if (isHeadAssignedHere(head, to) != LayoutTurnout.Geometry.NONE) { 1353 return true; 1354 } 1355 } 1356 1357 for (PositionablePoint po : layoutEditor.getPositionablePoints()) { 1358 if ((po.getEastBoundSignal().equals(sName) || ((uName != null) 1359 && (po.getEastBoundSignal().equals(uName))))) { 1360 return true; 1361 } 1362 if ((po.getWestBoundSignal().equals(sName) || ((uName != null) 1363 && (po.getWestBoundSignal().equals(uName))))) { 1364 return true; 1365 } 1366 } 1367 1368 for (LevelXing x : layoutEditor.getLevelXings()) { 1369 if ( (x.getSignalAName().equals(sName) || ((uName != null) 1370 && (x.getSignalAName().equals(uName))))) { 1371 return true; 1372 } 1373 if ( (x.getSignalBName().equals(sName) || ((uName != null) 1374 && (x.getSignalBName().equals(uName))))) { 1375 return true; 1376 } 1377 if ( (x.getSignalCName().equals(sName) || ((uName != null) 1378 && (x.getSignalCName().equals(uName))))) { 1379 return true; 1380 } 1381 if ( (x.getSignalDName().equals(sName) || ((uName != null) 1382 && (x.getSignalDName().equals(uName))))) { 1383 return true; 1384 } 1385 } 1386 return false; 1387 } //isHeadAssignedAnywhere 1388 1389 /** 1390 * Removes the assignment of the specified SignalHead to either a turnout, a 1391 * positionable point, or a level crossing wherever it is assigned. 1392 * @param head the signal head to be removed. 1393 */ 1394 public void removeAssignment(@Nonnull SignalHead head) { 1395 String sName = head.getSystemName(); 1396 String uName = head.getUserName(); 1397 for (LayoutTurnout to : layoutEditor.getLayoutTurnouts()) { 1398 if ((to.getSignalA1Name().equals(sName) || ((uName != null) 1399 && to.getSignalA1Name().equals(uName)))) { 1400 to.setSignalA1Name(""); 1401 } 1402 if ((to.getSignalA2Name().equals(sName) || ((uName != null) 1403 && to.getSignalA2Name().equals(uName)))) { 1404 to.setSignalA2Name(""); 1405 } 1406 if ((to.getSignalA3Name().equals(sName) || ((uName != null) 1407 && to.getSignalA3Name().equals(uName)))) { 1408 to.setSignalA3Name(""); 1409 } 1410 if ((to.getSignalB1Name().equals(sName) || ((uName != null) 1411 && to.getSignalB1Name().equals(uName)))) { 1412 to.setSignalB1Name(""); 1413 } 1414 if ((to.getSignalB2Name().equals(sName) || ((uName != null) 1415 && to.getSignalB2Name().equals(uName)))) { 1416 to.setSignalB2Name(""); 1417 } 1418 if ((to.getSignalC1Name().equals(sName) || ((uName != null) 1419 && to.getSignalC1Name().equals(uName)))) { 1420 to.setSignalC1Name(""); 1421 } 1422 if ((to.getSignalC2Name().equals(sName) || ((uName != null) 1423 && to.getSignalC2Name().equals(uName)))) { 1424 to.setSignalC2Name(""); 1425 } 1426 if ((to.getSignalD1Name().equals(sName) || ((uName != null) 1427 && to.getSignalD1Name().equals(uName)))) { 1428 to.setSignalD1Name(""); 1429 } 1430 if ((to.getSignalD2Name().equals(sName) || ((uName != null) 1431 && to.getSignalD2Name().equals(uName)))) { 1432 to.setSignalD2Name(""); 1433 } 1434 } 1435 for (PositionablePoint po : layoutEditor.getPositionablePoints()) { 1436 if (po.getEastBoundSignal().equals(sName) || po.getEastBoundSignal().equals(uName)) { 1437 po.setEastBoundSignal(""); 1438 } 1439 if (po.getWestBoundSignal().equals(sName) || po.getWestBoundSignal().equals(uName)) { 1440 po.setWestBoundSignal(""); 1441 } 1442 } 1443 for (LevelXing x : layoutEditor.getLevelXings()) { 1444 if ( (x.getSignalAName().equals(sName) || ((uName != null) 1445 && (x.getSignalAName().equals(uName))))) { 1446 x.setSignalAName(""); 1447 } 1448 if ( (x.getSignalBName().equals(sName) || ((uName != null) 1449 && (x.getSignalBName().equals(uName))))) { 1450 x.setSignalBName(""); 1451 } 1452 if ( (x.getSignalCName().equals(sName) || ((uName != null) 1453 && (x.getSignalCName().equals(uName))))) { 1454 x.setSignalCName(""); 1455 } 1456 if ( (x.getSignalDName().equals(sName) || ((uName != null) 1457 && (x.getSignalDName().equals(uName))))) { 1458 x.setSignalDName(""); 1459 } 1460 } 1461 } //removeAssignment 1462 1463 /** 1464 * Removes the SignalHead with the specified name from the panel and from 1465 * assignment to any turnout, positionable point, or level crossing. 1466 * @param signalName name of signal head to be removed. 1467 */ 1468 public void removeSignalHeadFromPanel(@CheckForNull String signalName) { 1469 if ((signalName == null) || signalName.isEmpty()) { 1470 return; 1471 } 1472 SignalHead head = InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(signalName); 1473 if (head != null) { 1474 removeAssignment(head); 1475 layoutEditor.removeSignalHead(head); 1476 } 1477 } 1478 1479 /* 1480 * Initializes a BlockBossLogic for creation of a signal logic for the signal 1481 * head named in "signalHeadName". 1482 * Should not be called until enough informmation has been gathered to allow 1483 * configuration of the Simple Signal Logic. 1484 */ 1485 public boolean initializeBlockBossLogic(@Nonnull String signalHeadName) { 1486 logic = BlockBossLogic.getStoppedObject(signalHeadName); 1487 return true; 1488 } 1489 1490 /* 1491 * Finalizes a successfully created signal logic 1492 */ 1493 public void finalizeBlockBossLogic() { 1494 if (logic == null) { 1495 return; 1496 } 1497 InstanceManager.getDefault(BlockBossLogicProvider.class).register(logic); 1498 logic.start(); 1499 logic = null; 1500 } 1501 1502 /* 1503 * Returns the signal head at the end of the block "track" is assigned to. 1504 * "track" is the Track Segment leaving "object". 1505 * "object" must be either an anchor point or one of the connecting 1506 * points of a turnout or level crossing. 1507 * Note: returns 'null' is signal is not present where it is expected, or 1508 * if an End Bumper is reached. To test for end bumper, use the 1509 * associated routine "reachedEndBumper()". Reaching a turntable ray 1510 * track connection is considered reaching an end bumper. 1511 * Note: Normally this routine requires a signal at any turnout it finds. 1512 * However, if 'skipIncludedTurnout' is true, this routine will skip 1513 * over an absent signal at an included turnout, that is a turnout 1514 * with its throat track segment and its continuing track segment in 1515 * the same block. When this happens, the user is warned. 1516 */ 1517 @CheckReturnValue 1518 public SignalHead getNextSignalFromObject(@Nonnull TrackSegment track, 1519 @Nonnull Object object, 1520 @Nonnull String signalHeadName, @Nonnull JmriJFrame frame) { 1521 hitEndBumper = false; 1522 auxSignal = null; 1523 TrackSegment t = track; 1524 Object obj = object; 1525 boolean inBlock = true; 1526 HitPointType type; // = LayoutEditor.HitPointType.NONE; 1527 Object connect = null; 1528 while (inBlock) { 1529 if (t.getConnect1() == obj) { 1530 type = t.getType2(); 1531 connect = t.getConnect2(); 1532 } else if (t.getConnect2() == obj) { 1533 type = t.getType1(); 1534 connect = t.getConnect1(); 1535 } else { 1536 log.error("Error obj not connected to {}!", t.getName()); 1537 return null; 1538 } 1539 if (type == HitPointType.POS_POINT) { 1540 PositionablePoint p = (PositionablePoint) connect; 1541 if (p.getType() == PositionablePoint.PointType.END_BUMPER) { 1542 hitEndBumper = true; 1543 return null; 1544 } 1545 if (p.getConnect1() == t) { 1546 t = p.getConnect2(); 1547 } else { 1548 t = p.getConnect1(); 1549 } 1550 if (t == null) { 1551 return null; 1552 } 1553 if (track.getLayoutBlock() != t.getLayoutBlock()) { 1554 //p is a block boundary - should be signalled 1555 String signalName; 1556 if (isAtWestEndOfAnchor(t, p)) { 1557 signalName = p.getWestBoundSignal(); 1558 } else { 1559 signalName = p.getEastBoundSignal(); 1560 } 1561 if (signalName.isEmpty()) { 1562 return null; 1563 } 1564 return InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(signalName); 1565 } 1566 obj = p; 1567 } else if (type == HitPointType.TURNOUT_A) { 1568 //Reached turnout throat, should be signalled 1569 LayoutTurnout to = (LayoutTurnout) connect; 1570 String signalName = to.getSignalA2Name(); 1571 if (!signalName.isEmpty()) { 1572 auxSignal = InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(signalName); 1573 } 1574 signalName = to.getSignalA1Name(); 1575 if (signalName.isEmpty()) { 1576 if (!layoutEditor.isIncludedTurnoutSkipped()) { 1577 return null; 1578 } 1579 t = getContinuingTrack(to, type); 1580 if ((t == null) || (track.getLayoutBlock() != t.getLayoutBlock())) { 1581 return null; 1582 } 1583 warnOfSkippedTurnout(frame, to.getTurnoutName(), signalHeadName); 1584 obj = to; 1585 } else { 1586 return InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(signalName); 1587 } 1588 } else if (type == HitPointType.TURNOUT_B) { 1589 //Reached turnout continuing, should be signalled 1590 LayoutTurnout to = (LayoutTurnout) connect; 1591 String signalName = to.getSignalB2Name(); 1592 if (to.getContinuingSense() == Turnout.THROWN) { 1593 signalName = to.getSignalC2Name(); 1594 } 1595 if (!signalName.isEmpty()) { 1596 auxSignal = InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(signalName); 1597 } 1598 if (to.getContinuingSense() == Turnout.CLOSED) { 1599 signalName = to.getSignalB1Name(); 1600 } else { 1601 signalName = to.getSignalC1Name(); 1602 } 1603 if (signalName.isEmpty()) { 1604 if (!layoutEditor.isIncludedTurnoutSkipped()) { 1605 return null; 1606 } 1607 t = getContinuingTrack(to, type); 1608 if ((t == null) || (track.getLayoutBlock() != t.getLayoutBlock())) { 1609 return null; 1610 } 1611 warnOfSkippedTurnout(frame, to.getTurnoutName(), signalHeadName); 1612 obj = to; 1613 } else { 1614 return InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(signalName); 1615 } 1616 } else if (type == HitPointType.TURNOUT_C) { 1617 //Reached turnout diverging, should be signalled 1618 LayoutTurnout to = (LayoutTurnout) connect; 1619 String signalName = to.getSignalC2Name(); 1620 if (to.getContinuingSense() == Turnout.THROWN) { 1621 signalName = to.getSignalB2Name(); 1622 } 1623 if (!signalName.isEmpty()) { 1624 auxSignal = InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(signalName); 1625 } 1626 if (to.getContinuingSense() == Turnout.CLOSED) { 1627 signalName = to.getSignalC1Name(); 1628 } else { 1629 signalName = to.getSignalB1Name(); 1630 } 1631 if (signalName.isEmpty()) { 1632 if (!layoutEditor.isIncludedTurnoutSkipped()) { 1633 return null; 1634 } 1635 t = getContinuingTrack(to, type); 1636 if ((t == null) || (track.getLayoutBlock() != t.getLayoutBlock())) { 1637 return null; 1638 } 1639 warnOfSkippedTurnout(frame, to.getTurnoutName(), signalHeadName); 1640 obj = to; 1641 } else { 1642 return InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(signalName); 1643 } 1644 } else if (type == HitPointType.TURNOUT_D) { 1645 //Reached turnout xover 4, should be signalled 1646 LayoutTurnout to = (LayoutTurnout) connect; 1647 String signalName = to.getSignalD2Name(); 1648 if (!signalName.isEmpty()) { 1649 auxSignal = InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(signalName); 1650 } 1651 signalName = to.getSignalD1Name(); 1652 if (signalName.isEmpty()) { 1653 if (!layoutEditor.isIncludedTurnoutSkipped()) { 1654 return null; 1655 } 1656 t = getContinuingTrack(to, type); 1657 if ((t == null) || (track.getLayoutBlock() != t.getLayoutBlock())) { 1658 return null; 1659 } 1660 warnOfSkippedTurnout(frame, to.getTurnoutName(), signalHeadName); 1661 obj = to; 1662 } else { 1663 return InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(signalName); 1664 } 1665 } else if (type == HitPointType.LEVEL_XING_A) { 1666 //Reached level crossing that may or may not be a block boundary 1667 LevelXing x = (LevelXing) connect; 1668 String signalName = x.getSignalAName(); 1669 if ( !signalName.isEmpty() ) { 1670 return InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(signalName); 1671 } 1672 t = (TrackSegment) x.getConnectC(); 1673 if (t == null) { 1674 return null; 1675 } 1676 if (track.getLayoutBlock() != t.getLayoutBlock()) { 1677 return null; 1678 } 1679 obj = x; 1680 } else if (type == HitPointType.LEVEL_XING_B) { 1681 //Reached level crossing that may or may not be a block boundary 1682 LevelXing x = (LevelXing) connect; 1683 String signalName = x.getSignalBName(); 1684 if ( !signalName.isEmpty() ) { 1685 return InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(signalName); 1686 } 1687 t = (TrackSegment) x.getConnectD(); 1688 if (t == null) { 1689 return null; 1690 } 1691 if (track.getLayoutBlock() != t.getLayoutBlock()) { 1692 return null; 1693 } 1694 obj = x; 1695 } else if (type == HitPointType.LEVEL_XING_C) { 1696 //Reached level crossing that may or may not be a block boundary 1697 LevelXing x = (LevelXing) connect; 1698 String signalName = x.getSignalCName(); 1699 if ( !signalName.isEmpty() ) { 1700 return InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(signalName); 1701 } 1702 t = (TrackSegment) x.getConnectA(); 1703 if (t == null) { 1704 return null; 1705 } 1706 if (track.getLayoutBlock() != t.getLayoutBlock()) { 1707 return null; 1708 } 1709 obj = x; 1710 } else if (type == HitPointType.LEVEL_XING_D) { 1711 //Reached level crossing that may or may not be a block boundary 1712 LevelXing x = (LevelXing) connect; 1713 String signalName = x.getSignalDName(); 1714 if ( !signalName.isEmpty() ) { 1715 return InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(signalName); 1716 } 1717 t = (TrackSegment) x.getConnectB(); 1718 if (t == null) { 1719 return null; 1720 } 1721 if (track.getLayoutBlock() != t.getLayoutBlock()) { 1722 return null; 1723 } 1724 obj = x; 1725 } else if (type == HitPointType.SLIP_A) { 1726 LayoutSlip sl = (LayoutSlip) connect; 1727 String signalName = sl.getSignalA2Name(); 1728 if (!signalName.isEmpty()) { 1729 auxSignal = InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(signalName); 1730 } 1731 signalName = sl.getSignalA1Name(); 1732 if (signalName.isEmpty()) { 1733 if (!layoutEditor.isIncludedTurnoutSkipped()) { 1734 return null; 1735 } 1736 t = getContinuingTrack(sl, type); 1737 if ((t == null) || (track.getLayoutBlock() != t.getLayoutBlock())) { 1738 return null; 1739 } 1740 warnOfSkippedTurnout(frame, sl.getTurnoutName(), signalHeadName); 1741 obj = sl; 1742 } else { 1743 return InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(signalName); 1744 } 1745 } else if (type == HitPointType.SLIP_B) { 1746 LayoutSlip sl = (LayoutSlip) connect; 1747 String signalName; 1748 if (sl.getTurnoutType() == LayoutSlip.TurnoutType.DOUBLE_SLIP) { 1749 signalName = sl.getSignalB2Name(); 1750 if (!signalName.isEmpty()) { 1751 auxSignal = InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(signalName); 1752 } 1753 } 1754 signalName = sl.getSignalB1Name(); 1755 if (signalName.isEmpty()) { 1756 if (!layoutEditor.isIncludedTurnoutSkipped()) { 1757 return null; 1758 } 1759 t = getContinuingTrack(sl, type); 1760 if ((t == null) || (track.getLayoutBlock() != t.getLayoutBlock())) { 1761 return null; 1762 } 1763 warnOfSkippedTurnout(frame, sl.getTurnoutName(), signalHeadName); 1764 obj = sl; 1765 } else { 1766 return InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(signalName); 1767 } 1768 } else if (type == HitPointType.SLIP_C) { 1769 LayoutSlip sl = (LayoutSlip) connect; 1770 String signalName; 1771 if (sl.getTurnoutType() == LayoutSlip.TurnoutType.DOUBLE_SLIP) { 1772 signalName = sl.getSignalC2Name(); 1773 if (!signalName.isEmpty()) { 1774 auxSignal = InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(signalName); 1775 } 1776 } 1777 signalName = sl.getSignalC1Name(); 1778 if (signalName.isEmpty()) { 1779 if (!layoutEditor.isIncludedTurnoutSkipped()) { 1780 return null; 1781 } 1782 t = getContinuingTrack(sl, type); 1783 if ((t == null) || (track.getLayoutBlock() != t.getLayoutBlock())) { 1784 return null; 1785 } 1786 warnOfSkippedTurnout(frame, sl.getTurnoutName(), signalHeadName); 1787 obj = sl; 1788 } else { 1789 return InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(signalName); 1790 } 1791 } else if (type == HitPointType.SLIP_D) { 1792 LayoutSlip sl = (LayoutSlip) connect; 1793 String signalName = sl.getSignalD2Name(); 1794 if (!signalName.isEmpty()) { 1795 auxSignal = InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(signalName); 1796 } 1797 signalName = sl.getSignalD1Name(); 1798 if (signalName.isEmpty()) { 1799 if (!layoutEditor.isIncludedTurnoutSkipped()) { 1800 return null; 1801 } 1802 t = getContinuingTrack(sl, type); 1803 if ((t == null) || (track.getLayoutBlock() != t.getLayoutBlock())) { 1804 return null; 1805 } 1806 warnOfSkippedTurnout(frame, sl.getTurnoutName(), signalHeadName); 1807 obj = sl; 1808 } else { 1809 return InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(signalName); 1810 } 1811 } else if (HitPointType.isTurntableRayHitType(type)) { 1812 hitEndBumper = true; 1813 return null; 1814 } 1815 } 1816 return null; 1817 } //getNextSignalFromObject 1818 1819 private boolean hitEndBumper = false; 1820 1821 private void warnOfSkippedTurnout( 1822 @Nonnull JFrame frame, 1823 @Nonnull String turnoutName, 1824 @Nonnull String signalHeadName) { 1825 JmriJOptionPane.showMessageDialog(frame, 1826 Bundle.getMessage("SignalsWarn2", 1827 new Object[]{turnoutName, signalHeadName}), 1828 Bundle.getMessage("WarningTitle"), 1829 JmriJOptionPane.WARNING_MESSAGE); 1830 } 1831 1832 @CheckReturnValue 1833 private TrackSegment getContinuingTrack(@Nonnull LayoutTurnout to, HitPointType type) { 1834 LayoutTurnout.TurnoutType ty = to.getTurnoutType(); 1835 if ((ty == LayoutTurnout.TurnoutType.RH_TURNOUT) || (ty == LayoutTurnout.TurnoutType.LH_TURNOUT)) { 1836 if (type == HitPointType.TURNOUT_A) { 1837 if (to.getContinuingSense() == Turnout.CLOSED) { 1838 return (TrackSegment) to.getConnectB(); 1839 } else { 1840 return (TrackSegment) to.getConnectC(); 1841 } 1842 } else { 1843 return (TrackSegment) to.getConnectA(); 1844 } 1845 } else if ((ty == LayoutTurnout.TurnoutType.DOUBLE_XOVER) || (ty == LayoutTurnout.TurnoutType.RH_XOVER) 1846 || (ty == LayoutTurnout.TurnoutType.LH_XOVER)) { 1847 if (type == HitPointType.TURNOUT_A) { 1848 return (TrackSegment) to.getConnectB(); 1849 } else if (type == HitPointType.TURNOUT_B) { 1850 return (TrackSegment) to.getConnectA(); 1851 } else if (type == HitPointType.TURNOUT_C) { 1852 return (TrackSegment) to.getConnectD(); 1853 } else if (type == HitPointType.TURNOUT_D) { 1854 return (TrackSegment) to.getConnectC(); 1855 } 1856 } 1857 log.error("Bad connection type around turnout {}", to.getTurnoutName()); 1858 return null; 1859 } 1860 1861 /* 1862 * Returns 'true' if an end bumper was reached during the last call to 1863 * GetNextSignalFromObject. Also used in the odd case of reaching a 1864 * turntable ray track connection, which is treated as an end 1865 * bumper here. 1866 */ 1867 public boolean reachedEndBumper() { 1868 return hitEndBumper; 1869 } 1870 1871 /* 1872 * Returns 'true' if "track" enters a block boundary at the west(north) end of 1873 * "point". Returns "false" otherwise. If track is neither horizontal or 1874 * vertical, assumes horizontal, as done when setting signals at block boundary. 1875 * "track" is a TrackSegment connected to "point". 1876 * "point" is an anchor point serving as a block boundary. 1877 * <p> 1878 * This is the member function method, which is preferred. See the static 1879 * method following. 1880 */ 1881 public boolean isAtWestEndOfAnchor(TrackSegment t, PositionablePoint p) { 1882 return LayoutEditorTools.isAtWestEndOfAnchor(layoutEditor, t, p); // invoke status locally 1883 } 1884 1885 1886 /* 1887 * Returns 'true' if "track" enters a block boundary at the west(north) end of 1888 * "point". Returns "false" otherwise. If track is neither horizontal or 1889 * vertical, assumes horizontal, as done when setting signals at block boundary. 1890 * "track" is a TrackSegment connected to "point". 1891 * "point" is an anchor point serving as a block boundary. 1892 * <p> 1893 * This is the static form, which requires context information from 1894 * a passed LayoutEditor reference; the member function is preferred because 1895 * some day we want to get rid of the LayoutEditor combined pseudo-global and panel reference. 1896 */ 1897 public static boolean isAtWestEndOfAnchor(LayoutEditor layoutEditor, TrackSegment t, PositionablePoint p) { 1898 if (p.getType() == PositionablePoint.PointType.EDGE_CONNECTOR) { 1899 if (p.getConnect1() == t) { 1900 if (p.getConnect1Dir() == Path.NORTH || p.getConnect1Dir() == Path.WEST) { 1901 return false; 1902 } 1903 return true; 1904 } else { 1905 if (p.getConnect1Dir() == Path.NORTH || p.getConnect1Dir() == Path.WEST) { 1906 return true; 1907 } 1908 return false; 1909 } 1910 1911 } 1912 TrackSegment tx = null; 1913 if (p.getConnect1() == t) { 1914 tx = p.getConnect2(); 1915 } else if (p.getConnect2() == t) { 1916 tx = p.getConnect1(); 1917 } else { 1918 log.error("track not connected to anchor point"); 1919 return false; 1920 } 1921 1922 Point2D coords1; 1923 if (t.getConnect1() == p) { 1924 coords1 = layoutEditor.getCoords(t.getConnect2(), t.getType2()); 1925 } else { 1926 coords1 = layoutEditor.getCoords(t.getConnect1(), t.getType1()); 1927 } 1928 1929 Point2D coords2; 1930 if (tx != null) { 1931 if (tx.getConnect1() == p) { 1932 coords2 = layoutEditor.getCoords(tx.getConnect2(), tx.getType2()); 1933 } else { 1934 coords2 = layoutEditor.getCoords(tx.getConnect1(), tx.getType1()); 1935 } 1936 } else { 1937 if (t.getConnect1() == p) { 1938 coords2 = layoutEditor.getCoords(t.getConnect1(), t.getType1()); 1939 } else { 1940 coords2 = layoutEditor.getCoords(t.getConnect2(), t.getType2()); 1941 } 1942 } 1943 1944 double delX = coords1.getX() - coords2.getX(); 1945 double delY = coords1.getY() - coords2.getY(); 1946 if (Math.abs(delX) > 2.0 * Math.abs(delY)) { 1947 //track is primarily horizontal 1948 if (delX > 0.0) { 1949 return false; 1950 } else { 1951 return true; 1952 } 1953 } else if (Math.abs(delY) > 2.0 * Math.abs(delX)) { 1954 //track is primarily vertical 1955 if (delY > 0.0) { 1956 return false; 1957 } else { 1958 return true; 1959 } 1960 } 1961 // track is not primarily horizontal or vertical; assume horizontal 1962 // log.error ("Track is not vertical or horizontal at anchor"); 1963 if (delX > 0.0) { 1964 return false; 1965 } 1966 return true; 1967 } 1968 1969 /*===========================*\ 1970 |* setSignalsAtBlockBoundary *| 1971 \*===========================*/ 1972 /** 1973 * Tool to set signals at a block boundary, including placing the signal 1974 * icons and setup of Simple Signal Logic for each signal head 1975 * <p> 1976 * Block boundary must be at an Anchor Point on the LayoutEditor panel. 1977 */ 1978 //operational variables for Set Signals at Block Boundary tool 1979 private JmriJFrame setSignalsAtBlockBoundaryFrame = null; 1980 private boolean setSignalsAtBlockBoundaryOpenFlag = false; 1981 private boolean setSignalsAtBlockBoundaryFromMenuFlag = false; 1982 1983 private JLabel block1NameLabel = null; 1984 private JLabel block2NameLabel = null; 1985 1986 private final NamedBeanComboBox<Block> block1IDComboBox = new NamedBeanComboBox<>( 1987 InstanceManager.getDefault(BlockManager.class), 1988 null, DisplayOptions.DISPLAYNAME); 1989 private final NamedBeanComboBox<Block> block2IDComboBox = new NamedBeanComboBox<>( 1990 InstanceManager.getDefault(BlockManager.class), 1991 null, DisplayOptions.DISPLAYNAME); 1992 1993 private final NamedBeanComboBox<SignalHead> eastBoundSignalHeadComboBox = new NamedBeanComboBox<>( 1994 InstanceManager.getDefault(SignalHeadManager.class), 1995 null, DisplayOptions.DISPLAYNAME); 1996 private final NamedBeanComboBox<SignalHead> westBoundSignalHeadComboBox = new NamedBeanComboBox<>( 1997 InstanceManager.getDefault(SignalHeadManager.class), 1998 null, DisplayOptions.DISPLAYNAME); 1999 2000 private final JCheckBox setEastBound = new JCheckBox(Bundle.getMessage("PlaceHead")); 2001 private final JCheckBox setupLogicEastBound = new JCheckBox(Bundle.getMessage("SetLogic")); 2002 private final JCheckBox setWestBound = new JCheckBox(Bundle.getMessage("PlaceHead")); 2003 private final JCheckBox setupLogicWestBound = new JCheckBox(Bundle.getMessage("SetLogic")); 2004 2005 private JButton getAnchorSavedSignalHeads = null; 2006 private JButton changeSignalAtBoundaryIcon = null; 2007 private JButton setSignalsAtBlockBoundaryDone = null; 2008 private JButton setSignalsAtBlockBoundaryCancel = null; 2009 2010 private LayoutBlock block1 = null; 2011 private LayoutBlock block2 = null; 2012 2013 private TrackSegment eastTrack = null; 2014 private TrackSegment westTrack = null; 2015 2016 private PositionablePoint boundary = null; 2017 private SignalHead eastBoundHead = null; 2018 private SignalHead westBoundHead = null; 2019 2020 private boolean showWest = true; 2021 private boolean showEast = true; 2022 2023 //display dialog for Set Signals at Block Boundary tool 2024 public void setSignalsAtBlockBoundaryFromMenu(PositionablePoint p, 2025 MultiIconEditor theEditor, 2026 JFrame theFrame) { 2027 boundary = p; 2028 2029 //if this is an edge connector... 2030 if ((p.getType() == PositionablePoint.PointType.EDGE_CONNECTOR) && ((p.getLinkedPoint() == null) 2031 || (p.getLinkedPoint().getConnect1() == null))) { 2032 if (p.getConnect1Dir() == Path.EAST || p.getConnect1Dir() == Path.SOUTH) { 2033 showWest = false; 2034 } else { 2035 showEast = false; 2036 } 2037 block1IDComboBox.setSelectedItem(boundary.getConnect1().getLayoutBlock().getBlock()); 2038 } else { 2039 block1IDComboBox.setSelectedItem(boundary.getConnect1().getLayoutBlock().getBlock()); 2040 block2IDComboBox.setSelectedItem(boundary.getConnect2().getLayoutBlock().getBlock()); 2041 } 2042 setSignalsAtBlockBoundaryFromMenuFlag = true; 2043 setSignalsAtBlockBoundary(theEditor, theFrame); 2044 setSignalsAtBlockBoundaryFromMenuFlag = false; 2045 } 2046 2047 public void setSignalsAtBlockBoundary(MultiIconEditor theEditor, JFrame theFrame) { 2048 signalIconEditor = theEditor; 2049 signalFrame = theFrame; 2050 2051 //Initialize if needed 2052 if (setSignalsAtBlockBoundaryFrame == null) { 2053 setSignalsAtBlockBoundaryOpenFlag = false; 2054 setSignalsAtBlockBoundaryFrame = new JmriJFrame(Bundle.getMessage("SignalsAtBoundary"), false, true); 2055 oneFrameToRuleThemAll(setSignalsAtBlockBoundaryFrame); 2056 setSignalsAtBlockBoundaryFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 2057 setSignalsAtBlockBoundaryFrame.addHelpMenu("package.jmri.jmrit.display.SetSignalsAtBoundary", true); 2058 setSignalsAtBlockBoundaryFrame.setLocation(70, 30); 2059 Container theContentPane = setSignalsAtBlockBoundaryFrame.getContentPane(); 2060 theContentPane.setLayout(new BoxLayout(theContentPane, BoxLayout.Y_AXIS)); 2061 2062 JPanel panel11 = new JPanel(new FlowLayout()); 2063 block1NameLabel = new JLabel( 2064 Bundle.getMessage("MakeLabel", 2065 Bundle.getMessage("BeanNameBlock") + " 1 ")); 2066 panel11.add(block1NameLabel); 2067 panel11.add(block1IDComboBox); 2068 block1IDComboBox.setToolTipText(Bundle.getMessage("SignalsBlockNameHintNW")); 2069 theContentPane.add(panel11); 2070 2071 JPanel panel12 = new JPanel(new FlowLayout()); 2072 block2NameLabel = new JLabel( 2073 Bundle.getMessage("MakeLabel", 2074 Bundle.getMessage("BeanNameBlock") 2075 + " 2 " + Bundle.getMessage("Name"))); 2076 panel12.add(block2NameLabel); 2077 panel12.add(block2IDComboBox); 2078 block2IDComboBox.setToolTipText(Bundle.getMessage("SignalsBlockNameHintSE")); 2079 theContentPane.add(panel12); 2080 theContentPane.add(new JSeparator(JSeparator.HORIZONTAL)); 2081 2082 JPanel panel2 = new JPanel(new FlowLayout()); 2083 JLabel shTitle = new JLabel(Bundle.getMessage("SignalHeads")); 2084 panel2.add(shTitle); 2085 panel2.add(new JLabel(" ")); 2086 panel2.add(getAnchorSavedSignalHeads = new JButton(Bundle.getMessage("GetSaved"))); 2087 getAnchorSavedSignalHeads.addActionListener(this::getSavedAnchorSignals); 2088 getAnchorSavedSignalHeads.setToolTipText(Bundle.getMessage("GetSavedHint")); 2089 theContentPane.add(panel2); 2090 if (showEast) { 2091 JPanel panel21 = new JPanel(new FlowLayout()); 2092 JLabel eastBoundLabel = new JLabel(Bundle.getMessage("East/SouthBound") + ": "); 2093 panel21.add(eastBoundLabel); 2094 panel21.add(eastBoundSignalHeadComboBox); 2095 theContentPane.add(panel21); 2096 eastBoundSignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadEastNameHint")); 2097 2098 JPanel panel22 = new JPanel(new FlowLayout()); 2099 panel22.add(new JLabel(" ")); 2100 panel22.add(setEastBound); 2101 setEastBound.setToolTipText(Bundle.getMessage("AnchorPlaceHeadHint")); 2102 panel22.add(new JLabel(" ")); 2103 if (showWest) { 2104 panel22.add(setupLogicEastBound); 2105 setupLogicEastBound.setToolTipText(Bundle.getMessage("SetLogicHint")); 2106 } 2107 theContentPane.add(panel22); 2108 } 2109 if (showWest) { 2110 JPanel panel31 = new JPanel(new FlowLayout()); 2111 JLabel westBoundLabel = new JLabel(Bundle.getMessage("West/NorthBound") + ": "); 2112 panel31.add(westBoundLabel); 2113 panel31.add(westBoundSignalHeadComboBox); 2114 theContentPane.add(panel31); 2115 westBoundSignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadWestNameHint")); 2116 2117 JPanel panel32 = new JPanel(new FlowLayout()); 2118 panel32.add(new JLabel(" ")); 2119 panel32.add(setWestBound); 2120 setWestBound.setToolTipText(Bundle.getMessage("AnchorPlaceHeadHint")); 2121 panel32.add(new JLabel(" ")); 2122 if (showEast) { 2123 panel32.add(setupLogicWestBound); 2124 setupLogicWestBound.setToolTipText(Bundle.getMessage("SetLogicHint")); 2125 } 2126 theContentPane.add(panel32); 2127 } 2128 2129 theContentPane.add(new JSeparator(JSeparator.HORIZONTAL)); 2130 2131 JPanel panel6 = new JPanel(new FlowLayout()); 2132 panel6.add(changeSignalAtBoundaryIcon = new JButton(Bundle.getMessage("ChangeSignalIcon"))); 2133 changeSignalAtBoundaryIcon.addActionListener((ActionEvent e) -> signalFrame.setVisible(true)); 2134 changeSignalAtBoundaryIcon.setToolTipText(Bundle.getMessage("ChangeSignalIconHint")); 2135 panel6.add(new JLabel(" ")); 2136 panel6.add(setSignalsAtBlockBoundaryDone = new JButton(Bundle.getMessage("ButtonDone"))); 2137 setSignalsAtBlockBoundaryDone.addActionListener(this::setSignalsAtBlockBoundaryDonePressed); 2138 setSignalsAtBlockBoundaryDone.setToolTipText(Bundle.getMessage("DoneHint", Bundle.getMessage("ButtonDone"))); 2139 2140 panel6.add(setSignalsAtBlockBoundaryCancel = new JButton(Bundle.getMessage("ButtonCancel"))); 2141 setSignalsAtBlockBoundaryCancel.addActionListener(this::setSignalsAtBlockBoundaryCancelPressed); 2142 setSignalsAtBlockBoundaryCancel.setToolTipText(Bundle.getMessage("CancelHint", Bundle.getMessage("ButtonCancel"))); 2143 theContentPane.add(panel6); 2144 2145 //make this button the default button (return or enter activates) 2146 JRootPane rootPane = SwingUtilities.getRootPane(setSignalsAtBlockBoundaryDone); 2147 if (rootPane != null) { //this should never happen but just in case... 2148 rootPane.setDefaultButton(setSignalsAtBlockBoundaryDone); 2149 } 2150 2151 setSignalsAtBlockBoundaryFrame.addWindowListener(new WindowAdapter() { 2152 @Override 2153 public void windowClosing(WindowEvent e) { 2154 setSignalsAtBlockBoundaryCancelPressed(null); 2155 } 2156 }); 2157 } 2158 2159 block1IDComboBox.setVisible(!setSignalsAtBlockBoundaryFromMenuFlag); 2160 block2IDComboBox.setVisible(!setSignalsAtBlockBoundaryFromMenuFlag); 2161 2162 if (setSignalsAtBlockBoundaryFromMenuFlag) { 2163 getSavedAnchorSignals(null); 2164 block1NameLabel.setText(Bundle.getMessage("MakeLabel", 2165 Bundle.getMessage("BeanNameBlock") 2166 + " 1 " + Bundle.getMessage("Name")) 2167 + boundary.getConnect1().getLayoutBlock().getId()); 2168 if (boundary.getConnect2() != null) { 2169 block2NameLabel.setText(Bundle.getMessage("MakeLabel", 2170 Bundle.getMessage("BeanNameBlock") 2171 + " 2 " + Bundle.getMessage("Name")) 2172 + boundary.getConnect2().getLayoutBlock().getId()); 2173 } 2174 } 2175 2176 if (!setSignalsAtBlockBoundaryOpenFlag) { 2177 setSignalsAtBlockBoundaryFrame.setPreferredSize(null); 2178 setSignalsAtBlockBoundaryFrame.pack(); 2179 setSignalsAtBlockBoundaryOpenFlag = true; 2180 } 2181 setSignalsAtBlockBoundaryFrame.setVisible(true); 2182 } //setSignalsAtBlockBoundary 2183 2184 private void getSavedAnchorSignals(ActionEvent a) { 2185 if (!getBlockInformation()) { 2186 return; 2187 } 2188 eastBoundSignalHeadComboBox.setSelectedItem(boundary.getEastBoundSignalHead()); 2189 westBoundSignalHeadComboBox.setSelectedItem(boundary.getWestBoundSignalHead()); 2190 } 2191 2192 private void setSignalsAtBlockBoundaryCancelPressed(ActionEvent a) { 2193 setSignalsAtBlockBoundaryOpenFlag = false; 2194 setSignalsAtBlockBoundaryFrame.setVisible(false); 2195 } 2196 2197 private void setSignalsAtBlockBoundaryDonePressed(ActionEvent a) { 2198 if (!getBlockInformation()) { 2199 return; 2200 } 2201 eastBoundHead = getSignalHeadFromEntry(eastBoundSignalHeadComboBox, false, setSignalsAtBlockBoundaryFrame); 2202 westBoundHead = getSignalHeadFromEntry(westBoundSignalHeadComboBox, false, setSignalsAtBlockBoundaryFrame); 2203 if ((eastBoundHead == null) && (westBoundHead == null)) { 2204 JmriJOptionPane.showMessageDialog(setSignalsAtBlockBoundaryFrame, 2205 Bundle.getMessage("SignalsError12"), 2206 Bundle.getMessage("ErrorTitle"), 2207 JmriJOptionPane.ERROR_MESSAGE); 2208 return; 2209 } 2210 //place or update signals as requested 2211 String newEastBoundSignalName = eastBoundSignalHeadComboBox.getSelectedItemDisplayName(); 2212 if (newEastBoundSignalName == null) { 2213 newEastBoundSignalName = ""; 2214 } 2215 if ((eastBoundHead != null) && setEastBound.isSelected()) { 2216 if (isHeadOnPanel(eastBoundHead) 2217 && (eastBoundHead != getHeadFromName(boundary.getEastBoundSignal()))) { 2218 JmriJOptionPane.showMessageDialog(setSignalsAtBlockBoundaryFrame, 2219 Bundle.getMessage("SignalsError6", 2220 new Object[]{newEastBoundSignalName}), 2221 Bundle.getMessage("ErrorTitle"), 2222 JmriJOptionPane.ERROR_MESSAGE); 2223 return; 2224 } else { 2225 removeSignalHeadFromPanel(boundary.getEastBoundSignal()); 2226 placeEastBound(); 2227 removeAssignment(eastBoundHead); 2228 boundary.setEastBoundSignal(newEastBoundSignalName); 2229 needRedraw = true; 2230 } 2231 } else if ((eastBoundHead != null) 2232 && (eastBoundHead != getHeadFromName(boundary.getEastBoundSignal())) 2233 && (eastBoundHead != getHeadFromName(boundary.getWestBoundSignal()))) { 2234 if (isHeadOnPanel(eastBoundHead)) { 2235 JmriJOptionPane.showMessageDialog(setSignalsAtBlockBoundaryFrame, 2236 Bundle.getMessage("SignalsError13", 2237 new Object[]{newEastBoundSignalName}), 2238 Bundle.getMessage("ErrorTitle"), 2239 JmriJOptionPane.ERROR_MESSAGE); 2240 return; 2241 } else { 2242 removeSignalHeadFromPanel(boundary.getEastBoundSignal()); 2243 removeAssignment(eastBoundHead); 2244 boundary.setEastBoundSignal(newEastBoundSignalName); 2245 } 2246 //} else if ((eastBoundHead != null) 2247 // && (eastBoundHead == getHeadFromName(boundary.getWestBoundSignal()))) { 2248 //need to figure out what to do in this case. 2249 } 2250 String newWestBoundSignalName = westBoundSignalHeadComboBox.getSelectedItemDisplayName(); 2251 if (newWestBoundSignalName == null) { 2252 newWestBoundSignalName = ""; 2253 } 2254 if ((westBoundHead != null) && setWestBound.isSelected()) { 2255 if (isHeadOnPanel(westBoundHead) 2256 && (westBoundHead != getHeadFromName(boundary.getWestBoundSignal()))) { 2257 JmriJOptionPane.showMessageDialog(setSignalsAtBlockBoundaryFrame, 2258 Bundle.getMessage("SignalsError6", 2259 new Object[]{newWestBoundSignalName}), 2260 Bundle.getMessage("ErrorTitle"), 2261 JmriJOptionPane.ERROR_MESSAGE); 2262 return; 2263 } else { 2264 removeSignalHeadFromPanel(boundary.getWestBoundSignal()); 2265 placeWestBound(); 2266 removeAssignment(westBoundHead); 2267 boundary.setWestBoundSignal(newWestBoundSignalName); 2268 needRedraw = true; 2269 } 2270 } else if ((westBoundHead != null) 2271 && (westBoundHead != getHeadFromName(boundary.getEastBoundSignal())) 2272 && (westBoundHead != getHeadFromName(boundary.getWestBoundSignal()))) { 2273 if (isHeadOnPanel(westBoundHead)) { 2274 JmriJOptionPane.showMessageDialog(setSignalsAtBlockBoundaryFrame, 2275 Bundle.getMessage("SignalsError13", 2276 new Object[]{newWestBoundSignalName}), 2277 Bundle.getMessage("ErrorTitle"), 2278 JmriJOptionPane.ERROR_MESSAGE); 2279 return; 2280 } else { 2281 removeSignalHeadFromPanel(boundary.getWestBoundSignal()); 2282 removeAssignment(westBoundHead); 2283 boundary.setWestBoundSignal(newWestBoundSignalName); 2284 } 2285 //} else if ((westBoundHead != null) 2286 // && (westBoundHead == getHeadFromName(boundary.getEastBoundSignal()))) { 2287 //need to figure out what to do in this case. 2288 } 2289 if ((eastBoundHead != null) && setupLogicEastBound.isSelected()) { 2290 setLogicEastBound(); 2291 } 2292 if ((westBoundHead != null) && setupLogicWestBound.isSelected()) { 2293 setLogicWestBound(); 2294 } 2295 setSignalsAtBlockBoundaryOpenFlag = false; 2296 setSignalsAtBlockBoundaryFrame.setVisible(false); 2297 if (needRedraw) { 2298 layoutEditor.redrawPanel(); 2299 needRedraw = false; 2300 layoutEditor.setDirty(); 2301 } 2302 } //setSignalsAtBlockBoundaryDonePressed 2303 2304 /* 2305 * Do some thing here for end bumpers. 2306 */ 2307 private boolean getBlockInformation() { 2308 //might have to do something to trick it with an end bumper 2309 if (!setSignalsAtBlockBoundaryFromMenuFlag) { 2310 block1 = getBlockFromEntry(block1IDComboBox); 2311 if (block1 == null) { 2312 return false; 2313 } 2314 block2 = getBlockFromEntry(block2IDComboBox); 2315 if (block2 == null) { 2316 return false; 2317 } 2318 boundary = null; 2319 for (PositionablePoint p : layoutEditor.getPositionablePoints()) { 2320 if (p.getType() == PositionablePoint.PointType.ANCHOR || p.getType() == PositionablePoint.PointType.EDGE_CONNECTOR) { 2321 LayoutBlock bA = null; 2322 LayoutBlock bB = null; 2323 if (p.getConnect1() != null) { 2324 bA = p.getConnect1().getLayoutBlock(); 2325 } 2326 if (p.getConnect2() != null) { 2327 bB = p.getConnect2().getLayoutBlock(); 2328 } 2329 if ((bA != null) && (bB != null) && (bA != bB)) { 2330 if (((bA == block1) && (bB == block2)) 2331 || ((bA == block2) && (bB == block1))) { 2332 boundary = p; 2333 break; 2334 } 2335 } 2336 } 2337 } 2338 if (boundary == null) { 2339 JmriJOptionPane.showMessageDialog(setSignalsAtBlockBoundaryFrame, 2340 Bundle.getMessage("SignalsError7"), 2341 Bundle.getMessage("ErrorTitle"), 2342 JmriJOptionPane.ERROR_MESSAGE); 2343 return false; 2344 } 2345 } 2346 //set track orientation at boundary 2347 eastTrack = null; 2348 westTrack = null; 2349 TrackSegment track1 = boundary.getConnect1(); 2350 Point2D coords1; 2351 if (track1.getConnect1() == boundary) { 2352 coords1 = layoutEditor.getCoords(track1.getConnect2(), track1.getType2()); 2353 } else { 2354 coords1 = layoutEditor.getCoords(track1.getConnect1(), track1.getType1()); 2355 } 2356 TrackSegment track2 = boundary.getConnect2(); 2357 2358 if (boundary.getType() == PositionablePoint.PointType.END_BUMPER) { 2359 return true; 2360 } 2361 if (boundary.getType() == PositionablePoint.PointType.EDGE_CONNECTOR) { 2362 if (boundary.getConnect1Dir() == Path.EAST || boundary.getConnect1Dir() == Path.SOUTH) { 2363 eastTrack = track2; 2364 westTrack = track1; 2365 } else { 2366 westTrack = track2; 2367 eastTrack = track1; 2368 } 2369 return true; 2370 } 2371 Point2D coords2; 2372 if (track2.getConnect1() == boundary) { 2373 coords2 = layoutEditor.getCoords(track2.getConnect2(), track2.getType2()); 2374 } else { 2375 coords2 = layoutEditor.getCoords(track2.getConnect1(), track2.getType1()); 2376 } 2377 2378 placeSignalDirectionDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coords2, coords1)); 2379 2380 double delX = coords1.getX() - coords2.getX(); 2381 double delY = coords1.getY() - coords2.getY(); 2382 2383 if (Math.abs(delX) >= Math.abs(delY)) { 2384 if (delX > 0.0) { 2385 eastTrack = track1; 2386 westTrack = track2; 2387 } else { 2388 eastTrack = track2; 2389 westTrack = track1; 2390 } 2391 } else { 2392 if (delY > 0.0) { 2393 eastTrack = track1; //south 2394 westTrack = track2; //north 2395 } else { 2396 eastTrack = track2; //south 2397 westTrack = track1; //north 2398 } 2399 } 2400 return true; 2401 } //getBlockInformation 2402 2403 @CheckReturnValue 2404 private LayoutBlock getBlockFromEntry(@Nonnull NamedBeanComboBox<Block> blockNameComboBox) { 2405 return getBlockFromEntry(blockNameComboBox.getSelectedItemDisplayName()); 2406 } 2407 2408 @CheckReturnValue 2409 private LayoutBlock getBlockFromEntry(@CheckForNull String theBlockName) { 2410 if ((theBlockName == null) || theBlockName.isEmpty()) { 2411 JmriJOptionPane.showMessageDialog(setSignalsAtBlockBoundaryFrame, 2412 Bundle.getMessage("SignalsError9"), 2413 Bundle.getMessage("ErrorTitle"), 2414 JmriJOptionPane.ERROR_MESSAGE); 2415 return null; 2416 } 2417 LayoutBlock block = InstanceManager.getDefault(LayoutBlockManager.class).getByUserName(theBlockName); 2418 if (block == null) { 2419 block = InstanceManager.getDefault(LayoutBlockManager.class).getBySystemName(theBlockName); 2420 if (block == null) { 2421 JmriJOptionPane.showMessageDialog(setSignalsAtBlockBoundaryFrame, 2422 Bundle.getMessage("SignalsError10", 2423 new Object[]{theBlockName}), Bundle.getMessage("ErrorTitle"), 2424 JmriJOptionPane.ERROR_MESSAGE); 2425 return null; 2426 } 2427 } 2428 if (!block.isOnPanel(layoutEditor) 2429 && ((boundary == null) || boundary.getType() != PositionablePoint.PointType.EDGE_CONNECTOR)) { 2430 JmriJOptionPane.showMessageDialog(setSignalsAtBlockBoundaryFrame, 2431 Bundle.getMessage("SignalsError11", 2432 new Object[]{theBlockName}), Bundle.getMessage("ErrorTitle"), 2433 JmriJOptionPane.ERROR_MESSAGE); 2434 return null; 2435 } 2436 return (block); 2437 } 2438 2439 private void placeEastBound() { 2440 if (testIcon == null) { 2441 testIcon = signalIconEditor.getIcon(0); 2442 } 2443 String signalHeadName = eastBoundSignalHeadComboBox.getSelectedItemDisplayName(); 2444 if (signalHeadName == null) { 2445 signalHeadName = ""; 2446 } 2447 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 2448 2449 Point2D coords = layoutEditor.getLayoutTrackView(boundary).getCoordsCenter(); 2450 Point2D delta = new Point2D.Double(0.0, +shift); 2451 2452 delta = MathUtil.rotateDEG(delta, placeSignalDirectionDEG); 2453 Point2D where = MathUtil.add(coords, delta); 2454 setSignalHeadOnPanel(placeSignalDirectionDEG + 180.0, signalHeadName, where); 2455 } 2456 2457 private void placeWestBound() { 2458 if (testIcon == null) { 2459 testIcon = signalIconEditor.getIcon(0); 2460 } 2461 String signalHeadName = westBoundSignalHeadComboBox.getSelectedItemDisplayName(); 2462 if (signalHeadName == null) { 2463 signalHeadName = ""; 2464 } 2465 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 2466 2467 Point2D coords = layoutEditor.getLayoutTrackView(boundary).getCoordsCenter(); 2468 2469 Point2D delta = new Point2D.Double(0.0, -shift); 2470 delta = MathUtil.rotateDEG(delta, placeSignalDirectionDEG); 2471 Point2D where = MathUtil.add(coords, delta); 2472 setSignalHeadOnPanel(placeSignalDirectionDEG, signalHeadName, where); 2473 } 2474 2475 private void setLogicEastBound() { 2476 LayoutBlock eastBlock = eastTrack.getLayoutBlock(); 2477 Sensor eastBlockOccupancy = eastBlock.getOccupancySensor(); 2478 if (eastBlockOccupancy == null) { 2479 JmriJOptionPane.showMessageDialog(setSignalsAtBlockBoundaryFrame, 2480 Bundle.getMessage("InfoMessage4", 2481 new Object[]{eastBlock.getUserName()}), 2482 Bundle.getMessage("MessageTitle"), 2483 JmriJOptionPane.INFORMATION_MESSAGE); 2484 return; 2485 } 2486 PositionablePoint p = boundary; 2487 if (boundary.getType() == PositionablePoint.PointType.EDGE_CONNECTOR && eastTrack != boundary.getConnect1()) { 2488 p = boundary.getLinkedPoint(); 2489 } 2490 String newEastBoundSignalName = eastBoundSignalHeadComboBox.getSelectedItemDisplayName(); 2491 if (newEastBoundSignalName == null) { 2492 newEastBoundSignalName = ""; 2493 } 2494 SignalHead nextHead = getNextSignalFromObject(eastTrack, 2495 p, newEastBoundSignalName, setSignalsAtBlockBoundaryFrame); 2496 if ((nextHead == null) && (!reachedEndBumper())) { 2497 JmriJOptionPane.showMessageDialog(setSignalsAtBlockBoundaryFrame, 2498 Bundle.getMessage("InfoMessage5", 2499 new Object[]{eastBlock.getUserName()}), 2500 Bundle.getMessage("MessageTitle"), 2501 JmriJOptionPane.INFORMATION_MESSAGE); 2502 return; 2503 } 2504 2505 if (!initializeBlockBossLogic(newEastBoundSignalName)) { 2506 return; 2507 } 2508 logic.setMode(BlockBossLogic.SINGLEBLOCK); 2509 logic.setSensor1(eastBlockOccupancy.getDisplayName()); 2510 if (nextHead != null) { 2511 logic.setWatchedSignal1(nextHead.getDisplayName(), false); 2512 } 2513 if (auxSignal != null) { 2514 logic.setWatchedSignal1Alt(auxSignal.getDisplayName()); 2515 } 2516 finalizeBlockBossLogic(); 2517 } 2518 2519 private void setLogicWestBound() { 2520 LayoutBlock westBlock = westTrack.getLayoutBlock(); 2521 Sensor westBlockOccupancy = westBlock.getOccupancySensor(); 2522 if (westBlockOccupancy == null) { 2523 JmriJOptionPane.showMessageDialog(setSignalsAtBlockBoundaryFrame, 2524 Bundle.getMessage("InfoMessage4", 2525 new Object[]{westBlock.getUserName()}), 2526 Bundle.getMessage("MessageTitle"), 2527 JmriJOptionPane.INFORMATION_MESSAGE); 2528 return; 2529 } 2530 PositionablePoint p = boundary; 2531 if (boundary.getType() == PositionablePoint.PointType.EDGE_CONNECTOR && westTrack != boundary.getConnect1()) { 2532 p = boundary.getLinkedPoint(); 2533 } 2534 String newWestBoundSignalName = westBoundSignalHeadComboBox.getSelectedItemDisplayName(); 2535 if (newWestBoundSignalName == null) { 2536 newWestBoundSignalName = ""; 2537 } 2538 SignalHead nextHead = getNextSignalFromObject(westTrack, 2539 p, newWestBoundSignalName, setSignalsAtBlockBoundaryFrame); 2540 if ((nextHead == null) && (!reachedEndBumper())) { 2541 JmriJOptionPane.showMessageDialog(setSignalsAtBlockBoundaryFrame, 2542 Bundle.getMessage("InfoMessage5", 2543 new Object[]{westBlock.getUserName()}), 2544 Bundle.getMessage("MessageTitle"), 2545 JmriJOptionPane.INFORMATION_MESSAGE); 2546 return; 2547 } 2548 if (!initializeBlockBossLogic(newWestBoundSignalName)) { 2549 return; 2550 } 2551 logic.setMode(BlockBossLogic.SINGLEBLOCK); 2552 logic.setSensor1(westBlockOccupancy.getDisplayName()); 2553 if (nextHead != null) { 2554 logic.setWatchedSignal1(nextHead.getDisplayName(), false); 2555 } 2556 if (auxSignal != null) { 2557 logic.setWatchedSignal1Alt(auxSignal.getDisplayName()); 2558 } 2559 finalizeBlockBossLogic(); 2560 } 2561 2562 /*==========================*\ 2563 |* setSignalsAtXoverTurnout *| 2564 \*==========================*/ 2565 /** 2566 * Tool to set signals at a double crossover turnout, including placing the 2567 * signal icons and setup of Simple Signal Logic for each signal head 2568 * <p> 2569 * This tool assumes left facing signal head icons have been selected, and 2570 * will rotate the signal head icons accordingly. 2571 * <p> 2572 * This tool will place icons on the outside edge of the turnout. 2573 * <p> 2574 * At least one signal at each of the four connection points is required. A 2575 * second signal at each is optional. 2576 */ 2577 //operational variables for Set Signals at Double Crossover Turnout tool 2578 private JmriJFrame setSignalsAtXoverTurnoutFrame = null; 2579 private boolean setSignalsAtXoverTurnoutOpenFlag = false; 2580 private boolean setSignalsAtXoverTurnoutFromMenuFlag = false; 2581 2582 private final NamedBeanComboBox<SignalHead> a1SignalHeadComboBox = new NamedBeanComboBox<>( 2583 InstanceManager.getDefault(SignalHeadManager.class), 2584 null, DisplayOptions.DISPLAYNAME); 2585 private final NamedBeanComboBox<SignalHead> a2SignalHeadComboBox = new NamedBeanComboBox<>( 2586 InstanceManager.getDefault(SignalHeadManager.class), 2587 null, DisplayOptions.DISPLAYNAME); 2588 private final NamedBeanComboBox<SignalHead> b1SignalHeadComboBox = new NamedBeanComboBox<>( 2589 InstanceManager.getDefault(SignalHeadManager.class), 2590 null, DisplayOptions.DISPLAYNAME); 2591 private final NamedBeanComboBox<SignalHead> b2SignalHeadComboBox = new NamedBeanComboBox<>( 2592 InstanceManager.getDefault(SignalHeadManager.class), 2593 null, DisplayOptions.DISPLAYNAME); 2594 private final NamedBeanComboBox<SignalHead> c1SignalHeadComboBox = new NamedBeanComboBox<>( 2595 InstanceManager.getDefault(SignalHeadManager.class), 2596 null, DisplayOptions.DISPLAYNAME); 2597 private final NamedBeanComboBox<SignalHead> c2SignalHeadComboBox = new NamedBeanComboBox<>( 2598 InstanceManager.getDefault(SignalHeadManager.class), 2599 null, DisplayOptions.DISPLAYNAME); 2600 private final NamedBeanComboBox<SignalHead> d1SignalHeadComboBox = new NamedBeanComboBox<>( 2601 InstanceManager.getDefault(SignalHeadManager.class), 2602 null, DisplayOptions.DISPLAYNAME); 2603 private final NamedBeanComboBox<SignalHead> d2SignalHeadComboBox = new NamedBeanComboBox<>( 2604 InstanceManager.getDefault(SignalHeadManager.class), 2605 null, DisplayOptions.DISPLAYNAME); 2606 2607 private final JCheckBox setA1Head = new JCheckBox(Bundle.getMessage("PlaceHead")); 2608 private final JCheckBox setA2Head = new JCheckBox(Bundle.getMessage("PlaceHead")); 2609 private final JCheckBox setB1Head = new JCheckBox(Bundle.getMessage("PlaceHead")); 2610 private final JCheckBox setB2Head = new JCheckBox(Bundle.getMessage("PlaceHead")); 2611 private final JCheckBox setC1Head = new JCheckBox(Bundle.getMessage("PlaceHead")); 2612 private final JCheckBox setC2Head = new JCheckBox(Bundle.getMessage("PlaceHead")); 2613 private final JCheckBox setD1Head = new JCheckBox(Bundle.getMessage("PlaceHead")); 2614 private final JCheckBox setD2Head = new JCheckBox(Bundle.getMessage("PlaceHead")); 2615 2616 private final JCheckBox setupA1Logic = new JCheckBox(Bundle.getMessage("SetLogic")); 2617 private final JCheckBox setupA2Logic = new JCheckBox(Bundle.getMessage("SetLogic")); 2618 private final JCheckBox setupB1Logic = new JCheckBox(Bundle.getMessage("SetLogic")); 2619 private final JCheckBox setupB2Logic = new JCheckBox(Bundle.getMessage("SetLogic")); 2620 private final JCheckBox setupC1Logic = new JCheckBox(Bundle.getMessage("SetLogic")); 2621 private final JCheckBox setupC2Logic = new JCheckBox(Bundle.getMessage("SetLogic")); 2622 private final JCheckBox setupD1Logic = new JCheckBox(Bundle.getMessage("SetLogic")); 2623 private final JCheckBox setupD2Logic = new JCheckBox(Bundle.getMessage("SetLogic")); 2624 2625 private JButton getSavedXoverSignalHeads = null; 2626 private JButton changeXoverSignalIcon = null; 2627 private JButton setXoverSignalsDone = null; 2628 private JButton setXoverSignalsCancel = null; 2629 2630 private SignalHead a1Head = null; 2631 private SignalHead a2Head = null; 2632 private SignalHead b1Head = null; 2633 private SignalHead b2Head = null; 2634 private SignalHead c1Head = null; 2635 private SignalHead c2Head = null; 2636 private SignalHead d1Head = null; 2637 private SignalHead d2Head = null; 2638 2639 private LayoutTurnout.TurnoutType xoverType = LayoutTurnout.TurnoutType.DOUBLE_XOVER; // changes to RH_XOVER or LH_XOVER as required 2640 private LayoutTurnout.TurnoutType xoverCurr = LayoutTurnout.TurnoutType.NONE; // Controls creating the frame 2641 private String xoverTurnoutName = ""; 2642 private final JLabel xoverTurnoutNameLabel = new JLabel(""); 2643 2644 //display dialog for Set Signals at Crossover Turnout tool 2645 public void setSignalsAtXoverTurnoutFromMenu(@Nonnull LayoutTurnout to, 2646 @Nonnull MultiIconEditor theEditor, @Nonnull JFrame theFrame) { 2647 layoutTurnout = to; 2648 turnout = to.getTurnout(); 2649 xoverType = layoutTurnout.getTurnoutType(); 2650 if ((xoverType != LayoutTurnout.TurnoutType.DOUBLE_XOVER) && (xoverType != LayoutTurnout.TurnoutType.RH_XOVER) 2651 && (xoverType != LayoutTurnout.TurnoutType.LH_XOVER)) { 2652 log.error("entered Set Signals at XOver, with a non-crossover turnout"); 2653 return; 2654 } 2655 xoverTurnoutName = layoutTurnout.getTurnoutName(); 2656 setSignalsAtXoverTurnoutFromMenuFlag = true; 2657 setSignalsAtXoverTurnout(theEditor, theFrame); 2658 setSignalsAtXoverTurnoutFromMenuFlag = false; 2659 } 2660 2661 public void setSignalsAtXoverTurnout(@Nonnull MultiIconEditor theEditor, 2662 @Nonnull JFrame theFrame) { 2663 signalIconEditor = theEditor; 2664 signalFrame = theFrame; 2665 2666 if (!setSignalsAtXoverTurnoutFromMenuFlag) { 2667 2668 List<LayoutTurnout> xovers = new ArrayList<>(); 2669 for (LayoutTurnout layoutTurnout : layoutEditor.getLayoutTurnouts()) { 2670 if (layoutTurnout.isTurnoutTypeXover()) { 2671 xovers.add(layoutTurnout); 2672 } 2673 } 2674 JComboBox<LayoutTurnout> jcb = new JComboBox<>( 2675 xovers.toArray(new LayoutTurnout[xovers.size()])); 2676 jcb.setEditable(true); 2677 JmriJOptionPane.showMessageDialog(layoutEditor, jcb, 2678 Bundle.getMessage("MakeLabel", 2679 Bundle.getMessage("EnterXOverTurnout")), 2680 JmriJOptionPane.QUESTION_MESSAGE); 2681 LayoutTurnout layoutTurnout = (LayoutTurnout) jcb.getSelectedItem(); 2682 xoverTurnoutName = layoutTurnout.getTurnoutName(); 2683 2684 if (xoverTurnoutName.length() < 3) { 2685 return; 2686 } 2687 } 2688 2689 if (!getTurnoutInformation(true)) { 2690 return; 2691 } 2692 2693 //Initialize if needed which can be the first time or the crossover type has changed. 2694 if (setSignalsAtXoverTurnoutFrame == null || xoverCurr != xoverType) { 2695 xoverCurr = xoverType; 2696 setSignalsAtXoverTurnoutOpenFlag = false; 2697 setSignalsAtXoverTurnoutFrame = new JmriJFrame(Bundle.getMessage("SignalsAtXoverTurnout"), false, true); 2698 oneFrameToRuleThemAll(setSignalsAtXoverTurnoutFrame); 2699 setSignalsAtXoverTurnoutFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 2700 setSignalsAtXoverTurnoutFrame.addHelpMenu("package.jmri.jmrit.display.SetSignalsAtXoverTurnout", true); 2701 setSignalsAtXoverTurnoutFrame.setLocation(70, 30); 2702 Container theContentPane = setSignalsAtXoverTurnoutFrame.getContentPane(); 2703 theContentPane.setLayout(new BoxLayout(theContentPane, BoxLayout.Y_AXIS)); 2704 2705 JPanel panel1 = new JPanel(new FlowLayout()); 2706 panel1.add(xoverTurnoutNameLabel); 2707 theContentPane.add(panel1); 2708 theContentPane.add(new JSeparator(JSeparator.HORIZONTAL)); 2709 2710 JPanel panel2 = new JPanel(new FlowLayout()); 2711 JLabel shTitle = new JLabel(Bundle.getMessage("SignalHeads")); 2712 panel2.add(shTitle); 2713 panel2.add(new JLabel(" ")); 2714 panel2.add(getSavedXoverSignalHeads = new JButton(Bundle.getMessage("GetSaved"))); 2715 getSavedXoverSignalHeads.addActionListener(this::xoverTurnoutSignalsGetSaved); 2716 getSavedXoverSignalHeads.setToolTipText(Bundle.getMessage("GetSavedHint")); 2717 theContentPane.add(panel2); 2718 2719 theContentPane.add(new JSeparator(JSeparator.HORIZONTAL)); 2720 JPanel panel2a = new JPanel(new FlowLayout()); 2721 panel2a.add(new JLabel(" ")); 2722 panel2a.add(setPlaceAllHeads); 2723 setPlaceAllHeads.setToolTipText(Bundle.getMessage("PlaceAllHeadsHint")); 2724 setPlaceAllHeads.addActionListener((ActionEvent e) -> { 2725 boolean isSelected = setPlaceAllHeads.isSelected(); 2726 //(de)select all checkboxes 2727 setA1Head.setSelected(isSelected); 2728 setA2Head.setSelected(isSelected); 2729 setB1Head.setSelected(isSelected); 2730 setB2Head.setSelected(isSelected); 2731 setC1Head.setSelected(isSelected); 2732 setC2Head.setSelected(isSelected); 2733 setD1Head.setSelected(isSelected); 2734 setD2Head.setSelected(isSelected); 2735 }); 2736 panel2a.add(new JLabel(" ")); 2737 panel2a.add(setupAllLogic); 2738 setupAllLogic.setToolTipText(Bundle.getMessage("SetAllLogicHint")); 2739 setupAllLogic.addActionListener((ActionEvent e) -> { 2740 boolean isSelected = setupAllLogic.isSelected(); 2741 //(de)select all checkboxes 2742 setupA1Logic.setSelected(isSelected); 2743 setupA2Logic.setSelected(isSelected); 2744 setupB1Logic.setSelected(isSelected); 2745 setupB2Logic.setSelected(isSelected); 2746 setupC1Logic.setSelected(isSelected); 2747 setupC2Logic.setSelected(isSelected); 2748 setupD1Logic.setSelected(isSelected); 2749 setupD2Logic.setSelected(isSelected); 2750 }); 2751 theContentPane.add(panel2a); 2752 2753 JPanel panel21 = new JPanel(new FlowLayout()); 2754 JLabel a1Label = new JLabel( 2755 Bundle.getMessage("MakeLabel", 2756 Bundle.getMessage("XContinuing", "A"))); 2757 panel21.add(a1Label); 2758 panel21.add(a1SignalHeadComboBox); 2759 theContentPane.add(panel21); 2760 a1SignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 2761 2762 JPanel panel22 = new JPanel(new FlowLayout()); 2763 panel22.add(new JLabel(" ")); 2764 panel22.add(setA1Head); 2765 setA1Head.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 2766 panel22.add(new JLabel(" ")); 2767 panel22.add(setupA1Logic); 2768 setupA1Logic.setToolTipText(Bundle.getMessage("SetLogicHint")); 2769 theContentPane.add(panel22); 2770 if (!(xoverType == LayoutTurnout.TurnoutType.LH_XOVER)) { 2771 JPanel panel23 = new JPanel(new FlowLayout()); 2772 JLabel a2Label = new JLabel(Bundle.getMessage("MakeLabel", 2773 Bundle.getMessage("XDiverging", "A"))); 2774 panel23.add(a2Label); 2775 panel23.add(a2SignalHeadComboBox); 2776 theContentPane.add(panel23); 2777 a2SignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 2778 JPanel panel24 = new JPanel(new FlowLayout()); 2779 panel24.add(new JLabel(" ")); 2780 panel24.add(setA2Head); 2781 setA2Head.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 2782 panel24.add(new JLabel(" ")); 2783 panel24.add(setupA2Logic); 2784 setupA2Logic.setToolTipText(Bundle.getMessage("SetLogicHint")); 2785 theContentPane.add(panel24); 2786 } 2787 2788 JPanel panel31 = new JPanel(new FlowLayout()); 2789 JLabel b1Label = new JLabel(Bundle.getMessage("MakeLabel", 2790 Bundle.getMessage("XContinuing", "B"))); 2791 panel31.add(b1Label); 2792 panel31.add(b1SignalHeadComboBox); 2793 theContentPane.add(panel31); 2794 b1SignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 2795 2796 JPanel panel32 = new JPanel(new FlowLayout()); 2797 panel32.add(new JLabel(" ")); 2798 panel32.add(setB1Head); 2799 setB1Head.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 2800 panel32.add(new JLabel(" ")); 2801 panel32.add(setupB1Logic); 2802 setupB1Logic.setToolTipText(Bundle.getMessage("SetLogicHint")); 2803 theContentPane.add(panel32); 2804 if (!(xoverType == LayoutTurnout.TurnoutType.RH_XOVER)) { 2805 JPanel panel33 = new JPanel(new FlowLayout()); 2806 JLabel b2Label = new JLabel(Bundle.getMessage("MakeLabel", 2807 Bundle.getMessage("XDiverging", "B"))); 2808 panel33.add(b2Label); 2809 panel33.add(b2SignalHeadComboBox); 2810 theContentPane.add(panel33); 2811 b2SignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 2812 JPanel panel34 = new JPanel(new FlowLayout()); 2813 panel34.add(new JLabel(" ")); 2814 panel34.add(setB2Head); 2815 setB2Head.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 2816 panel34.add(new JLabel(" ")); 2817 panel34.add(setupB2Logic); 2818 setupB2Logic.setToolTipText(Bundle.getMessage("SetLogicHint")); 2819 theContentPane.add(panel34); 2820 } 2821 2822 JPanel panel41 = new JPanel(new FlowLayout()); 2823 JLabel c1Label = new JLabel(Bundle.getMessage("MakeLabel", 2824 Bundle.getMessage("XContinuing", "C"))); 2825 panel41.add(c1Label); 2826 panel41.add(c1SignalHeadComboBox); 2827 theContentPane.add(panel41); 2828 c1SignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 2829 2830 JPanel panel42 = new JPanel(new FlowLayout()); 2831 panel42.add(new JLabel(" ")); 2832 panel42.add(setC1Head); 2833 setC1Head.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 2834 panel42.add(new JLabel(" ")); 2835 panel42.add(setupC1Logic); 2836 setupC1Logic.setToolTipText(Bundle.getMessage("SetLogicHint")); 2837 theContentPane.add(panel42); 2838 if (!(xoverType == LayoutTurnout.TurnoutType.LH_XOVER)) { 2839 JPanel panel43 = new JPanel(new FlowLayout()); 2840 JLabel c2Label = new JLabel(Bundle.getMessage("MakeLabel", 2841 Bundle.getMessage("XDiverging", "C"))); 2842 panel43.add(c2Label); 2843 panel43.add(c2SignalHeadComboBox); 2844 theContentPane.add(panel43); 2845 c2SignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 2846 JPanel panel44 = new JPanel(new FlowLayout()); 2847 panel44.add(new JLabel(" ")); 2848 panel44.add(setC2Head); 2849 setC2Head.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 2850 panel44.add(new JLabel(" ")); 2851 panel44.add(setupC2Logic); 2852 setupC2Logic.setToolTipText(Bundle.getMessage("SetLogicHint")); 2853 theContentPane.add(panel44); 2854 } 2855 2856 JPanel panel51 = new JPanel(new FlowLayout()); 2857 JLabel d1Label = new JLabel(Bundle.getMessage("MakeLabel", 2858 Bundle.getMessage("XContinuing", "D"))); 2859 panel51.add(d1Label); 2860 panel51.add(d1SignalHeadComboBox); 2861 theContentPane.add(panel51); 2862 d1SignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 2863 2864 JPanel panel52 = new JPanel(new FlowLayout()); 2865 panel52.add(new JLabel(" ")); 2866 panel52.add(setD1Head); 2867 setD1Head.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 2868 panel52.add(new JLabel(" ")); 2869 panel52.add(setupD1Logic); 2870 setupD1Logic.setToolTipText(Bundle.getMessage("SetLogicHint")); 2871 theContentPane.add(panel52); 2872 if (xoverType != LayoutTurnout.TurnoutType.RH_XOVER) { 2873 JPanel panel53 = new JPanel(new FlowLayout()); 2874 JLabel d2Label = new JLabel(Bundle.getMessage("MakeLabel", 2875 Bundle.getMessage("XDiverging", "D"))); 2876 panel53.add(d2Label); 2877 panel53.add(d2SignalHeadComboBox); 2878 theContentPane.add(panel53); 2879 d2SignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 2880 JPanel panel54 = new JPanel(new FlowLayout()); 2881 panel54.add(new JLabel(" ")); 2882 panel54.add(setD2Head); 2883 setD2Head.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 2884 panel54.add(new JLabel(" ")); 2885 panel54.add(setupD2Logic); 2886 setupD2Logic.setToolTipText(Bundle.getMessage("SetLogicHint")); 2887 theContentPane.add(panel54); 2888 } 2889 theContentPane.add(new JSeparator(JSeparator.HORIZONTAL)); 2890 2891 JPanel panel6 = new JPanel(new FlowLayout()); 2892 panel6.add(changeXoverSignalIcon = new JButton(Bundle.getMessage("ChangeSignalIcon"))); 2893 changeXoverSignalIcon.addActionListener((ActionEvent e) -> signalFrame.setVisible(true)); 2894 changeXoverSignalIcon.setToolTipText(Bundle.getMessage("ChangeSignalIconHint")); 2895 panel6.add(new JLabel(" ")); 2896 panel6.add(setXoverSignalsDone = new JButton(Bundle.getMessage("ButtonDone"))); 2897 setXoverSignalsDone.addActionListener(this::setXoverSignalsDonePressed); 2898 setXoverSignalsDone.setToolTipText(Bundle.getMessage("DoneHint", Bundle.getMessage("ButtonDone"))); 2899 2900 panel6.add(setXoverSignalsCancel = new JButton(Bundle.getMessage("ButtonCancel"))); 2901 setXoverSignalsCancel.addActionListener(this::setXoverSignalsCancelPressed); 2902 setXoverSignalsCancel.setToolTipText(Bundle.getMessage("CancelHint", Bundle.getMessage("ButtonCancel"))); 2903 theContentPane.add(panel6); 2904 2905 //make this button the default button (return or enter activates) 2906 JRootPane rootPane = SwingUtilities.getRootPane(setXoverSignalsDone); 2907 if (rootPane != null) { 2908 rootPane.setDefaultButton(setXoverSignalsDone); 2909 } 2910 2911 setSignalsAtXoverTurnoutFrame.addWindowListener(new WindowAdapter() { 2912 @Override 2913 public void windowClosing(WindowEvent e) { 2914 setXoverSignalsCancelPressed(null); 2915 } 2916 }); 2917 } 2918 setPlaceAllHeads.setSelected(false); 2919 setupAllLogic.setSelected(false); 2920 2921 xoverTurnoutNameLabel.setText(Bundle.getMessage("MakeLabel", 2922 Bundle.getMessage("BeanNameTurnout") 2923 + " " + Bundle.getMessage("Name")) + xoverTurnoutName); 2924 xoverType = layoutTurnout.getTurnoutType(); 2925 2926 xoverTurnoutSignalsGetSaved(null); 2927 2928 if (!setSignalsAtXoverTurnoutOpenFlag) { 2929 setSignalsAtXoverTurnoutFrame.setPreferredSize(null); 2930 setSignalsAtXoverTurnoutFrame.pack(); 2931 setSignalsAtXoverTurnoutOpenFlag = true; 2932 } 2933 setSignalsAtXoverTurnoutFrame.setVisible(true); 2934 } //setSignalsAtXoverTurnout 2935 2936 private void xoverTurnoutSignalsGetSaved(ActionEvent a) { 2937 a1SignalHeadComboBox.setSelectedItem(layoutTurnout.getSignalA1()); 2938 a2SignalHeadComboBox.setSelectedItem(layoutTurnout.getSignalA2()); 2939 b1SignalHeadComboBox.setSelectedItem(layoutTurnout.getSignalB1()); 2940 b2SignalHeadComboBox.setSelectedItem(layoutTurnout.getSignalB2()); 2941 c1SignalHeadComboBox.setSelectedItem(layoutTurnout.getSignalC1()); 2942 c2SignalHeadComboBox.setSelectedItem(layoutTurnout.getSignalC2()); 2943 d1SignalHeadComboBox.setSelectedItem(layoutTurnout.getSignalD1()); 2944 d2SignalHeadComboBox.setSelectedItem(layoutTurnout.getSignalD2()); 2945 } 2946 2947 private void setXoverSignalsCancelPressed(ActionEvent a) { 2948 setSignalsAtXoverTurnoutOpenFlag = false; 2949 setSignalsAtXoverTurnoutFrame.setVisible(false); 2950 } 2951 2952 private void setXoverSignalsDonePressed(ActionEvent a) { 2953 if (!getXoverSignalHeadInformation()) { 2954 return; 2955 } 2956 //place signal icons if requested, and assign signal heads to this turnout 2957 String signalHeadName = a1SignalHeadComboBox.getSelectedItemDisplayName(); 2958 if (signalHeadName == null) { 2959 signalHeadName = ""; 2960 } 2961 if (setA1Head.isSelected()) { 2962 if (isHeadOnPanel(a1Head) 2963 && (a1Head != getHeadFromName(layoutTurnout.getSignalA1Name()))) { 2964 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 2965 Bundle.getMessage("SignalsError6", 2966 new Object[]{signalHeadName}), 2967 Bundle.getMessage("ErrorTitle"), 2968 JmriJOptionPane.ERROR_MESSAGE); 2969 return; 2970 } else { 2971 removeSignalHeadFromPanel(layoutTurnout.getSignalA1Name()); 2972 placeA1(); 2973 removeAssignment(a1Head); 2974 layoutTurnout.setSignalA1Name(signalHeadName); 2975 needRedraw = true; 2976 } 2977 } else { 2978 LayoutTurnout.Geometry assigned = isHeadAssignedHere(a1Head, layoutTurnout); 2979 if (assigned == LayoutTurnout.Geometry.NONE) { 2980 if (isHeadOnPanel(a1Head) 2981 && isHeadAssignedAnywhere(a1Head)) { 2982 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 2983 Bundle.getMessage("SignalsError8", 2984 new Object[]{signalHeadName}), 2985 Bundle.getMessage("ErrorTitle"), 2986 JmriJOptionPane.ERROR_MESSAGE); 2987 return; 2988 } else { 2989 removeSignalHeadFromPanel(layoutTurnout.getSignalA1Name()); 2990 removeAssignment(a1Head); 2991 layoutTurnout.setSignalA1Name(signalHeadName); 2992 } 2993 //} else if (assigned != A1) { 2994 //need to figure out what to do in this case. 2995 } 2996 } 2997 signalHeadName = a2SignalHeadComboBox.getSelectedItemDisplayName(); 2998 if (signalHeadName == null) { 2999 signalHeadName = ""; 3000 } 3001 if ((a2Head != null) && setA2Head.isSelected()) { 3002 if (isHeadOnPanel(a2Head) 3003 && (a2Head != getHeadFromName(layoutTurnout.getSignalA2Name()))) { 3004 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 3005 Bundle.getMessage("SignalsError6", 3006 new Object[]{signalHeadName}), 3007 Bundle.getMessage("ErrorTitle"), 3008 JmriJOptionPane.ERROR_MESSAGE); 3009 return; 3010 } else { 3011 removeSignalHeadFromPanel(layoutTurnout.getSignalA2Name()); 3012 placeA2(); 3013 removeAssignment(a2Head); 3014 layoutTurnout.setSignalA2Name(signalHeadName); 3015 needRedraw = true; 3016 } 3017 } else if (a2Head != null) { 3018 LayoutTurnout.Geometry assigned = isHeadAssignedHere(a2Head, layoutTurnout); 3019 if (assigned == LayoutTurnout.Geometry.NONE) { 3020 if (isHeadOnPanel(a2Head) 3021 && isHeadAssignedAnywhere(a2Head)) { 3022 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 3023 Bundle.getMessage("SignalsError8", 3024 new Object[]{signalHeadName}), 3025 Bundle.getMessage("ErrorTitle"), 3026 JmriJOptionPane.ERROR_MESSAGE); 3027 return; 3028 } else { 3029 removeSignalHeadFromPanel(layoutTurnout.getSignalA2Name()); 3030 removeAssignment(a2Head); 3031 layoutTurnout.setSignalA2Name(signalHeadName); 3032 } 3033 //} else if (assigned != A2) { 3034 //need to figure out what to do in this case. 3035 } 3036 } else { //a2Head known to be null here 3037 removeSignalHeadFromPanel(layoutTurnout.getSignalA2Name()); 3038 layoutTurnout.setSignalA2Name(""); 3039 } 3040 signalHeadName = b1SignalHeadComboBox.getSelectedItemDisplayName(); 3041 if (signalHeadName == null) { 3042 signalHeadName = ""; 3043 } 3044 if (setB1Head.isSelected()) { 3045 if (isHeadOnPanel(b1Head) 3046 && (b1Head != getHeadFromName(layoutTurnout.getSignalB1Name()))) { 3047 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 3048 Bundle.getMessage("SignalsError6", 3049 new Object[]{signalHeadName}), 3050 Bundle.getMessage("ErrorTitle"), 3051 JmriJOptionPane.ERROR_MESSAGE); 3052 return; 3053 } else { 3054 removeSignalHeadFromPanel(layoutTurnout.getSignalB1Name()); 3055 placeB1(); 3056 removeAssignment(b1Head); 3057 layoutTurnout.setSignalB1Name(signalHeadName); 3058 needRedraw = true; 3059 } 3060 } else { 3061 LayoutTurnout.Geometry assigned = isHeadAssignedHere(b1Head, layoutTurnout); 3062 if (assigned == LayoutTurnout.Geometry.NONE) { 3063 if (isHeadOnPanel(b1Head) 3064 && isHeadAssignedAnywhere(b1Head)) { 3065 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 3066 Bundle.getMessage("SignalsError8", 3067 new Object[]{signalHeadName}), 3068 Bundle.getMessage("ErrorTitle"), 3069 JmriJOptionPane.ERROR_MESSAGE); 3070 return; 3071 } else { 3072 removeSignalHeadFromPanel(layoutTurnout.getSignalB1Name()); 3073 removeAssignment(b1Head); 3074 layoutTurnout.setSignalB1Name(signalHeadName); 3075 } 3076 //} else if (assigned != B1) { 3077 //need to figure out what to do in this case. 3078 } 3079 } 3080 signalHeadName = b2SignalHeadComboBox.getSelectedItemDisplayName(); 3081 if (signalHeadName == null) { 3082 signalHeadName = ""; 3083 } 3084 if ((b2Head != null) && setB2Head.isSelected()) { 3085 if (isHeadOnPanel(b2Head) 3086 && (b2Head != getHeadFromName(layoutTurnout.getSignalB2Name()))) { 3087 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 3088 Bundle.getMessage("SignalsError6", 3089 new Object[]{signalHeadName}), 3090 Bundle.getMessage("ErrorTitle"), 3091 JmriJOptionPane.ERROR_MESSAGE); 3092 return; 3093 } else { 3094 removeSignalHeadFromPanel(layoutTurnout.getSignalB2Name()); 3095 placeB2(); 3096 removeAssignment(b2Head); 3097 layoutTurnout.setSignalB2Name(signalHeadName); 3098 needRedraw = true; 3099 } 3100 } else if (b2Head != null) { 3101 LayoutTurnout.Geometry assigned = isHeadAssignedHere(b2Head, layoutTurnout); 3102 if (assigned == LayoutTurnout.Geometry.NONE) { 3103 if (isHeadOnPanel(b2Head) 3104 && isHeadAssignedAnywhere(b2Head)) { 3105 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 3106 Bundle.getMessage("SignalsError8", 3107 new Object[]{signalHeadName}), 3108 Bundle.getMessage("ErrorTitle"), 3109 JmriJOptionPane.ERROR_MESSAGE); 3110 return; 3111 } else { 3112 removeSignalHeadFromPanel(layoutTurnout.getSignalB2Name()); 3113 removeAssignment(b2Head); 3114 layoutTurnout.setSignalB2Name(signalHeadName); 3115 } 3116 //} else if (assigned != B2) { 3117 //need to figure out what to do in this case. 3118 } 3119 } else { //b2Head known to be null here 3120 removeSignalHeadFromPanel(layoutTurnout.getSignalB2Name()); 3121 layoutTurnout.setSignalB2Name(""); 3122 } 3123 signalHeadName = c1SignalHeadComboBox.getSelectedItemDisplayName(); 3124 if (signalHeadName == null) { 3125 signalHeadName = ""; 3126 } 3127 if (setC1Head.isSelected()) { 3128 if (isHeadOnPanel(c1Head) 3129 && (c1Head != getHeadFromName(layoutTurnout.getSignalC1Name()))) { 3130 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 3131 Bundle.getMessage("SignalsError6", 3132 new Object[]{signalHeadName}), 3133 Bundle.getMessage("ErrorTitle"), 3134 JmriJOptionPane.ERROR_MESSAGE); 3135 return; 3136 } else { 3137 removeSignalHeadFromPanel(layoutTurnout.getSignalC1Name()); 3138 placeC1(); 3139 removeAssignment(c1Head); 3140 layoutTurnout.setSignalC1Name(signalHeadName); 3141 needRedraw = true; 3142 } 3143 } else { 3144 LayoutTurnout.Geometry assigned = isHeadAssignedHere(c1Head, layoutTurnout); 3145 if (assigned == LayoutTurnout.Geometry.NONE) { 3146 if (isHeadOnPanel(c1Head) 3147 && isHeadAssignedAnywhere(c1Head)) { 3148 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 3149 Bundle.getMessage("SignalsError8", 3150 new Object[]{signalHeadName}), 3151 Bundle.getMessage("ErrorTitle"), 3152 JmriJOptionPane.ERROR_MESSAGE); 3153 return; 3154 } else { 3155 removeSignalHeadFromPanel(layoutTurnout.getSignalC1Name()); 3156 removeAssignment(c1Head); 3157 layoutTurnout.setSignalC1Name(signalHeadName); 3158 } 3159 //} else if (assigned != C1) { 3160 //need to figure out what to do in this case. 3161 } 3162 } 3163 signalHeadName = c2SignalHeadComboBox.getSelectedItemDisplayName(); 3164 if (signalHeadName == null) { 3165 signalHeadName = ""; 3166 } 3167 if ((c2Head != null) && setC2Head.isSelected()) { 3168 if (isHeadOnPanel(c2Head) 3169 && (c2Head != getHeadFromName(layoutTurnout.getSignalC2Name()))) { 3170 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 3171 Bundle.getMessage("SignalsError6", 3172 new Object[]{signalHeadName}), 3173 Bundle.getMessage("ErrorTitle"), 3174 JmriJOptionPane.ERROR_MESSAGE); 3175 return; 3176 } else { 3177 removeSignalHeadFromPanel(layoutTurnout.getSignalC2Name()); 3178 placeC2(); 3179 removeAssignment(c2Head); 3180 layoutTurnout.setSignalC2Name(signalHeadName); 3181 needRedraw = true; 3182 } 3183 } else if (c2Head != null) { 3184 LayoutTurnout.Geometry assigned = isHeadAssignedHere(c2Head, layoutTurnout); 3185 if (assigned == LayoutTurnout.Geometry.NONE) { 3186 if (isHeadOnPanel(c2Head) 3187 && isHeadAssignedAnywhere(c2Head)) { 3188 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 3189 Bundle.getMessage("SignalsError8", 3190 new Object[]{signalHeadName}), 3191 Bundle.getMessage("ErrorTitle"), 3192 JmriJOptionPane.ERROR_MESSAGE); 3193 return; 3194 } else { 3195 removeSignalHeadFromPanel(layoutTurnout.getSignalC2Name()); 3196 removeAssignment(c2Head); 3197 layoutTurnout.setSignalC2Name(signalHeadName); 3198 } 3199 //} else if (assigned != C2) { 3200 //need to figure out what to do in this case. 3201 } 3202 } else { //c2Head known to be null here 3203 removeSignalHeadFromPanel(layoutTurnout.getSignalC2Name()); 3204 layoutTurnout.setSignalC2Name(""); 3205 } 3206 signalHeadName = d1SignalHeadComboBox.getSelectedItemDisplayName(); 3207 if (signalHeadName == null) { 3208 signalHeadName = ""; 3209 } 3210 if (setD1Head.isSelected()) { 3211 if (isHeadOnPanel(d1Head) 3212 && (d1Head != getHeadFromName(layoutTurnout.getSignalD1Name()))) { 3213 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 3214 Bundle.getMessage("SignalsError6", 3215 new Object[]{signalHeadName}), 3216 Bundle.getMessage("ErrorTitle"), 3217 JmriJOptionPane.ERROR_MESSAGE); 3218 return; 3219 } else { 3220 removeSignalHeadFromPanel(layoutTurnout.getSignalD1Name()); 3221 placeD1(); 3222 removeAssignment(d1Head); 3223 layoutTurnout.setSignalD1Name(signalHeadName); 3224 needRedraw = true; 3225 } 3226 } else { 3227 LayoutTurnout.Geometry assigned = isHeadAssignedHere(d1Head, layoutTurnout); 3228 if (assigned == LayoutTurnout.Geometry.NONE) { 3229 if (isHeadOnPanel(d1Head) 3230 && isHeadAssignedAnywhere(d1Head)) { 3231 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 3232 Bundle.getMessage("SignalsError8", 3233 new Object[]{signalHeadName}), 3234 Bundle.getMessage("ErrorTitle"), 3235 JmriJOptionPane.ERROR_MESSAGE); 3236 return; 3237 } else { 3238 removeSignalHeadFromPanel(layoutTurnout.getSignalD1Name()); 3239 removeAssignment(d1Head); 3240 layoutTurnout.setSignalD1Name(signalHeadName); 3241 } 3242 //} else if (assigned != D1) { 3243 //need to figure out what to do in this case. 3244 } 3245 } 3246 signalHeadName = d2SignalHeadComboBox.getSelectedItemDisplayName(); 3247 if (signalHeadName == null) { 3248 signalHeadName = ""; 3249 } 3250 if ((d2Head != null) && setD2Head.isSelected()) { 3251 if (isHeadOnPanel(d2Head) 3252 && (d2Head != getHeadFromName(layoutTurnout.getSignalD2Name()))) { 3253 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 3254 Bundle.getMessage("SignalsError6", 3255 new Object[]{signalHeadName}), 3256 Bundle.getMessage("ErrorTitle"), 3257 JmriJOptionPane.ERROR_MESSAGE); 3258 return; 3259 } else { 3260 removeSignalHeadFromPanel(layoutTurnout.getSignalD2Name()); 3261 placeD2(); 3262 removeAssignment(d2Head); 3263 layoutTurnout.setSignalD2Name(signalHeadName); 3264 needRedraw = true; 3265 } 3266 } else if (d2Head != null) { 3267 LayoutTurnout.Geometry assigned = isHeadAssignedHere(d2Head, layoutTurnout); 3268 if (assigned == LayoutTurnout.Geometry.NONE) { 3269 if (isHeadOnPanel(d2Head) 3270 && isHeadAssignedAnywhere(d2Head)) { 3271 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 3272 Bundle.getMessage("SignalsError8", 3273 new Object[]{signalHeadName}), 3274 Bundle.getMessage("ErrorTitle"), 3275 JmriJOptionPane.ERROR_MESSAGE); 3276 return; 3277 } else { 3278 removeSignalHeadFromPanel(layoutTurnout.getSignalD2Name()); 3279 removeAssignment(d2Head); 3280 layoutTurnout.setSignalD2Name(signalHeadName); 3281 } 3282 //} else if (assigned != D2) { 3283 //need to figure out what to do in this case. 3284 } 3285 } else { //d2Head known to be null here 3286 removeSignalHeadFromPanel(layoutTurnout.getSignalD2Name()); 3287 layoutTurnout.setSignalD2Name(""); 3288 } 3289 //setup logic if requested 3290 if (setupA1Logic.isSelected() || setupA2Logic.isSelected()) { 3291 if (xoverType == LayoutTurnout.TurnoutType.LH_XOVER) { 3292 setLogicXoverContinuing(a1Head, (TrackSegment) layoutTurnout.getConnectB()); 3293 } else { 3294 setLogicXover(a1Head, (TrackSegment) layoutTurnout.getConnectB(), a2Head, 3295 (TrackSegment) layoutTurnout.getConnectC(), setupA1Logic.isSelected(), 3296 setupA2Logic.isSelected()); 3297 } 3298 } 3299 if (setupB1Logic.isSelected() || setupB2Logic.isSelected()) { 3300 if (xoverType == LayoutTurnout.TurnoutType.RH_XOVER) { 3301 setLogicXoverContinuing(b1Head, (TrackSegment) layoutTurnout.getConnectA()); 3302 } else { 3303 setLogicXover(b1Head, (TrackSegment) layoutTurnout.getConnectA(), b2Head, 3304 (TrackSegment) layoutTurnout.getConnectD(), setupB1Logic.isSelected(), 3305 setupB2Logic.isSelected()); 3306 } 3307 } 3308 if (setupC1Logic.isSelected() || setupC2Logic.isSelected()) { 3309 if (xoverType == LayoutTurnout.TurnoutType.LH_XOVER) { 3310 setLogicXoverContinuing(c1Head, (TrackSegment) layoutTurnout.getConnectD()); 3311 } else { 3312 setLogicXover(c1Head, (TrackSegment) layoutTurnout.getConnectD(), c2Head, 3313 (TrackSegment) layoutTurnout.getConnectA(), setupC1Logic.isSelected(), 3314 setupC2Logic.isSelected()); 3315 } 3316 } 3317 if (setupD1Logic.isSelected() || setupD2Logic.isSelected()) { 3318 if (xoverType == LayoutTurnout.TurnoutType.RH_XOVER) { 3319 setLogicXoverContinuing(d1Head, (TrackSegment) layoutTurnout.getConnectC()); 3320 } else { 3321 setLogicXover(d1Head, (TrackSegment) layoutTurnout.getConnectC(), d2Head, 3322 (TrackSegment) layoutTurnout.getConnectB(), setupD1Logic.isSelected(), 3323 setupD2Logic.isSelected()); 3324 } 3325 } 3326 //make sure this layout turnout is not linked to another 3327 layoutTurnout.setLinkType(LayoutTurnout.LinkType.NO_LINK); 3328 layoutTurnout.setLinkedTurnoutName(""); 3329 //finish up 3330 setSignalsAtXoverTurnoutOpenFlag = false; 3331 setSignalsAtXoverTurnoutFrame.setVisible(false); 3332 if (needRedraw) { 3333 layoutEditor.redrawPanel(); 3334 needRedraw = false; 3335 layoutEditor.setDirty(); 3336 } 3337 } //setXoverSignalsDonePressed 3338 3339 private boolean getXoverSignalHeadInformation() { 3340 a1Head = getSignalHeadFromEntry(a1SignalHeadComboBox, true, setSignalsAtXoverTurnoutFrame); 3341 if (a1Head == null) { 3342 return false; 3343 } 3344 if (!(xoverType == LayoutTurnout.TurnoutType.LH_XOVER)) { 3345 a2Head = getSignalHeadFromEntry(a2SignalHeadComboBox, false, setSignalsAtXoverTurnoutFrame); 3346 } else { 3347 a2Head = null; 3348 } 3349 b1Head = getSignalHeadFromEntry(b1SignalHeadComboBox, true, setSignalsAtXoverTurnoutFrame); 3350 if (b1Head == null) { 3351 return false; 3352 } 3353 if (!(xoverType == LayoutTurnout.TurnoutType.RH_XOVER)) { 3354 b2Head = getSignalHeadFromEntry(b2SignalHeadComboBox, false, setSignalsAtXoverTurnoutFrame); 3355 } else { 3356 b2Head = null; 3357 } 3358 c1Head = getSignalHeadFromEntry(c1SignalHeadComboBox, true, setSignalsAtXoverTurnoutFrame); 3359 if (c1Head == null) { 3360 return false; 3361 } 3362 if (!(xoverType == LayoutTurnout.TurnoutType.LH_XOVER)) { 3363 c2Head = getSignalHeadFromEntry(c2SignalHeadComboBox, false, setSignalsAtXoverTurnoutFrame); 3364 } else { 3365 c2Head = null; 3366 } 3367 d1Head = getSignalHeadFromEntry(d1SignalHeadComboBox, true, setSignalsAtXoverTurnoutFrame); 3368 if (d1Head == null) { 3369 return false; 3370 } 3371 if (!(xoverType == LayoutTurnout.TurnoutType.RH_XOVER)) { 3372 d2Head = getSignalHeadFromEntry(d2SignalHeadComboBox, false, setSignalsAtXoverTurnoutFrame); 3373 } else { 3374 d2Head = null; 3375 } 3376 return true; 3377 } 3378 3379 private void placeA1() { 3380 if (testIcon == null) { 3381 testIcon = signalIconEditor.getIcon(0); 3382 } 3383 String signalHeadName = a1SignalHeadComboBox.getSelectedItemDisplayName(); 3384 if (signalHeadName == null) { 3385 signalHeadName = ""; 3386 } 3387 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 3388 3389 LayoutTurnoutView layoutTurnoutView = layoutEditor.getLayoutTurnoutView(layoutTurnout); 3390 3391 Point2D coordsA = layoutTurnoutView.getCoordsA(); 3392 Point2D delta = new Point2D.Double(0.0, +shift); 3393 3394 delta = MathUtil.rotateDEG(delta, placeSignalDirectionDEG); 3395 Point2D where = MathUtil.add(coordsA, delta); 3396 setSignalHeadOnPanel(placeSignalDirectionDEG + 180.0, signalHeadName, where); 3397 } 3398 3399 private void placeA2() { 3400 if (testIcon == null) { 3401 testIcon = signalIconEditor.getIcon(0); 3402 } 3403 String signalHeadName = a2SignalHeadComboBox.getSelectedItemDisplayName(); 3404 if (signalHeadName == null) { 3405 signalHeadName = ""; 3406 } 3407 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 3408 3409 LayoutTurnoutView layoutTurnoutView = layoutEditor.getLayoutTurnoutView(layoutTurnout); 3410 3411 Point2D coordsA = layoutTurnoutView.getCoordsA(); 3412 Point2D delta = new Point2D.Double(-2.0 * shift, +shift); 3413 3414 delta = MathUtil.rotateDEG(delta, placeSignalDirectionDEG); 3415 Point2D where = MathUtil.add(coordsA, delta); 3416 setSignalHeadOnPanel(placeSignalDirectionDEG + 180.0, signalHeadName, where); 3417 } 3418 3419 private void placeB1() { 3420 if (testIcon == null) { 3421 testIcon = signalIconEditor.getIcon(0); 3422 } 3423 String signalHeadName = b1SignalHeadComboBox.getSelectedItemDisplayName(); 3424 if (signalHeadName == null) { 3425 signalHeadName = ""; 3426 } 3427 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 3428 3429 LayoutTurnoutView layoutTurnoutView = layoutEditor.getLayoutTurnoutView(layoutTurnout); 3430 3431 Point2D coordsB = layoutTurnoutView.getCoordsB(); 3432 Point2D delta = new Point2D.Double(-shift, -shift); 3433 3434 delta = MathUtil.rotateDEG(delta, placeSignalDirectionDEG); 3435 Point2D where = MathUtil.add(coordsB, delta); 3436 setSignalHeadOnPanel(placeSignalDirectionDEG, signalHeadName, where); 3437 } 3438 3439 private void placeB2() { 3440 if (testIcon == null) { 3441 testIcon = signalIconEditor.getIcon(0); 3442 } 3443 String signalHeadName = b2SignalHeadComboBox.getSelectedItemDisplayName(); 3444 if (signalHeadName == null) { 3445 signalHeadName = ""; 3446 } 3447 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 3448 3449 LayoutTurnoutView layoutTurnoutView = layoutEditor.getLayoutTurnoutView(layoutTurnout); 3450 3451 Point2D coordsB = layoutTurnoutView.getCoordsB(); 3452 Point2D delta = new Point2D.Double(+shift, -shift); 3453 3454 delta = MathUtil.rotateDEG(delta, placeSignalDirectionDEG); 3455 Point2D where = MathUtil.add(coordsB, delta); 3456 setSignalHeadOnPanel(placeSignalDirectionDEG, signalHeadName, where); 3457 } 3458 3459 private void placeC1() { 3460 if (testIcon == null) { 3461 testIcon = signalIconEditor.getIcon(0); 3462 } 3463 String signalHeadName = c1SignalHeadComboBox.getSelectedItemDisplayName(); 3464 if (signalHeadName == null) { 3465 signalHeadName = ""; 3466 } 3467 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 3468 3469 LayoutTurnoutView layoutTurnoutView = layoutEditor.getLayoutTurnoutView(layoutTurnout); 3470 3471 Point2D coordsC = layoutTurnoutView.getCoordsC(); 3472 Point2D delta = new Point2D.Double(0.0, -shift); 3473 3474 delta = MathUtil.rotateDEG(delta, placeSignalDirectionDEG); 3475 Point2D where = MathUtil.add(coordsC, delta); 3476 setSignalHeadOnPanel(placeSignalDirectionDEG, signalHeadName, where); 3477 } 3478 3479 private void placeC2() { 3480 if (testIcon == null) { 3481 testIcon = signalIconEditor.getIcon(0); 3482 } 3483 String signalHeadName = c2SignalHeadComboBox.getSelectedItemDisplayName(); 3484 if (signalHeadName == null) { 3485 signalHeadName = ""; 3486 } 3487 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 3488 3489 LayoutTurnoutView layoutTurnoutView = layoutEditor.getLayoutTurnoutView(layoutTurnout); 3490 3491 Point2D coordsC = layoutTurnoutView.getCoordsC(); 3492 Point2D delta = new Point2D.Double(+2.0 * shift, -shift); 3493 3494 delta = MathUtil.rotateDEG(delta, placeSignalDirectionDEG); 3495 Point2D where = MathUtil.add(coordsC, delta); 3496 setSignalHeadOnPanel(placeSignalDirectionDEG, signalHeadName, where); 3497 } 3498 3499 private void placeD1() { 3500 if (testIcon == null) { 3501 testIcon = signalIconEditor.getIcon(0); 3502 } 3503 String signalHeadName = d1SignalHeadComboBox.getSelectedItemDisplayName(); 3504 if (signalHeadName == null) { 3505 signalHeadName = ""; 3506 } 3507 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 3508 3509 LayoutTurnoutView layoutTurnoutView = layoutEditor.getLayoutTurnoutView(layoutTurnout); 3510 3511 Point2D coordsD = layoutTurnoutView.getCoordsD(); 3512 Point2D delta = new Point2D.Double(+shift, +shift); 3513 3514 delta = MathUtil.rotateDEG(delta, placeSignalDirectionDEG); 3515 Point2D where = MathUtil.add(coordsD, delta); 3516 setSignalHeadOnPanel(placeSignalDirectionDEG + 180.0, signalHeadName, where); 3517 } 3518 3519 private void placeD2() { 3520 if (testIcon == null) { 3521 testIcon = signalIconEditor.getIcon(0); 3522 } 3523 String signalHeadName = d2SignalHeadComboBox.getSelectedItemDisplayName(); 3524 if (signalHeadName == null) { 3525 signalHeadName = ""; 3526 } 3527 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 3528 3529 LayoutTurnoutView layoutTurnoutView = layoutEditor.getLayoutTurnoutView(layoutTurnout); 3530 3531 Point2D coordsD = layoutTurnoutView.getCoordsD(); 3532 Point2D delta = new Point2D.Double(-shift, +shift); 3533 3534 delta = MathUtil.rotateDEG(delta, placeSignalDirectionDEG); 3535 Point2D where = MathUtil.add(coordsD, delta); 3536 setSignalHeadOnPanel(placeSignalDirectionDEG + 180.0, signalHeadName, where); 3537 } 3538 3539 @SuppressWarnings("null") 3540 private void setLogicXover(SignalHead head, TrackSegment track, SignalHead secondHead, TrackSegment track2, 3541 boolean setup1, boolean setup2) { 3542 if ((track == null) && setup1) { 3543 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 3544 Bundle.getMessage("InfoMessage7"), 3545 Bundle.getMessage("MessageTitle"), 3546 JmriJOptionPane.INFORMATION_MESSAGE); 3547 return; 3548 } 3549 Sensor occupancy = null; 3550 SignalHead nextHead = null; 3551 if ((track != null) && setup1) { 3552 LayoutBlock block = track.getLayoutBlock(); 3553 if (block == null) { 3554 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 3555 Bundle.getMessage("InfoMessage6"), 3556 Bundle.getMessage("MessageTitle"), 3557 JmriJOptionPane.INFORMATION_MESSAGE); 3558 return; 3559 } 3560 occupancy = block.getOccupancySensor(); 3561 if (occupancy == null) { 3562 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 3563 Bundle.getMessage("InfoMessage4", 3564 new Object[]{block.getUserName()}), 3565 Bundle.getMessage("MessageTitle"), 3566 JmriJOptionPane.INFORMATION_MESSAGE); 3567 return; 3568 } 3569 nextHead = getNextSignalFromObject(track, 3570 layoutTurnout, head.getSystemName(), setSignalsAtXoverTurnoutFrame); 3571 if ((nextHead == null) && (!reachedEndBumper())) { 3572 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 3573 Bundle.getMessage("InfoMessage5", 3574 new Object[]{block.getUserName()}), 3575 Bundle.getMessage("MessageTitle"), 3576 JmriJOptionPane.INFORMATION_MESSAGE); 3577 return; 3578 } 3579 if (secondHead != null) { 3580 if (!initializeBlockBossLogic(head.getDisplayName())) { 3581 return; 3582 } 3583 logic.setMode(BlockBossLogic.TRAILINGMAIN); 3584 logic.setTurnout(turnout.getDisplayName()); 3585 logic.setSensor1(occupancy.getDisplayName()); 3586 if (nextHead != null) { 3587 logic.setWatchedSignal1(nextHead.getDisplayName(), false); 3588 } 3589 if (auxSignal != null) { 3590 logic.setWatchedSignal1Alt(auxSignal.getDisplayName()); 3591 } 3592 finalizeBlockBossLogic(); 3593 } 3594 } 3595 if ((secondHead != null) && !setup2) { 3596 return; 3597 } 3598 SignalHead savedAuxSignal = auxSignal; 3599 if (track2 == null) { 3600 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 3601 Bundle.getMessage("InfoMessage7"), 3602 Bundle.getMessage("MessageTitle"), 3603 JmriJOptionPane.INFORMATION_MESSAGE); 3604 return; 3605 } 3606 LayoutBlock block2 = track2.getLayoutBlock(); 3607 if (block2 == null) { 3608 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 3609 Bundle.getMessage("InfoMessage6"), 3610 Bundle.getMessage("MessageTitle"), 3611 JmriJOptionPane.INFORMATION_MESSAGE); 3612 return; 3613 } 3614 Sensor occupancy2 = block2.getOccupancySensor(); 3615 if (occupancy2 == null) { 3616 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 3617 Bundle.getMessage("InfoMessage4", 3618 new Object[]{block2.getUserName()}), 3619 Bundle.getMessage("MessageTitle"), 3620 JmriJOptionPane.INFORMATION_MESSAGE); 3621 return; 3622 } 3623 String signalHeadName = head.getSystemName(); 3624 if (secondHead != null) { 3625 signalHeadName = secondHead.getSystemName(); 3626 } 3627 SignalHead nextHead2 = getNextSignalFromObject(track2, 3628 layoutTurnout, signalHeadName, setSignalsAtXoverTurnoutFrame); 3629 if ((nextHead2 == null) && (!reachedEndBumper())) { 3630 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 3631 Bundle.getMessage("InfoMessage5", 3632 new Object[]{block2.getUserName()}), 3633 Bundle.getMessage("MessageTitle"), 3634 JmriJOptionPane.INFORMATION_MESSAGE); 3635 return; 3636 } 3637 if ((secondHead == null) && (track != null) && setup1) { 3638 if (!initializeBlockBossLogic(head.getDisplayName())) { 3639 return; 3640 } 3641 logic.setMode(BlockBossLogic.FACING); 3642 logic.setTurnout(turnout.getDisplayName()); 3643 logic.setWatchedSensor1(occupancy.getDisplayName()); 3644 logic.setWatchedSensor2(occupancy2.getDisplayName()); 3645 if (nextHead != null) { 3646 logic.setWatchedSignal1(nextHead.getDisplayName(), false); 3647 } 3648 if (savedAuxSignal != null) { 3649 logic.setWatchedSignal1Alt(savedAuxSignal.getDisplayName()); 3650 } 3651 if (nextHead2 != null) { 3652 logic.setWatchedSignal2(nextHead2.getDisplayName()); 3653 } 3654 if (auxSignal != null) { 3655 logic.setWatchedSignal2Alt(auxSignal.getDisplayName()); 3656 } 3657 logic.setLimitSpeed2(true); 3658 finalizeBlockBossLogic(); 3659 } else if ((secondHead != null) && setup2) { 3660 if (!initializeBlockBossLogic(secondHead.getDisplayName())) { 3661 return; 3662 } 3663 logic.setMode(BlockBossLogic.TRAILINGDIVERGING); 3664 logic.setTurnout(turnout.getDisplayName()); 3665 logic.setSensor1(occupancy2.getDisplayName()); 3666 if (nextHead2 != null) { 3667 logic.setWatchedSignal1(nextHead2.getDisplayName(), false); 3668 } 3669 if (auxSignal != null) { 3670 logic.setWatchedSignal1Alt(auxSignal.getDisplayName()); 3671 } 3672 logic.setLimitSpeed2(true); 3673 finalizeBlockBossLogic(); 3674 } 3675 } //setLogicXover 3676 3677 private void setLogicXoverContinuing(SignalHead head, TrackSegment track) { 3678 if (track == null) { 3679 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 3680 Bundle.getMessage("InfoMessage7"), 3681 Bundle.getMessage("MessageTitle"), 3682 JmriJOptionPane.INFORMATION_MESSAGE); 3683 return; 3684 } 3685 LayoutBlock block = track.getLayoutBlock(); 3686 if (block == null) { 3687 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 3688 Bundle.getMessage("InfoMessage6"), 3689 Bundle.getMessage("MessageTitle"), 3690 JmriJOptionPane.INFORMATION_MESSAGE); 3691 return; 3692 } 3693 Sensor occupancy = block.getOccupancySensor(); 3694 if (occupancy == null) { 3695 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 3696 Bundle.getMessage("InfoMessage4", 3697 new Object[]{block.getUserName()}), 3698 Bundle.getMessage("MessageTitle"), 3699 JmriJOptionPane.INFORMATION_MESSAGE); 3700 return; 3701 } 3702 SignalHead nextHead = getNextSignalFromObject(track, 3703 layoutTurnout, head.getSystemName(), setSignalsAtXoverTurnoutFrame); 3704 if ((nextHead == null) && (!reachedEndBumper())) { 3705 JmriJOptionPane.showMessageDialog(setSignalsAtXoverTurnoutFrame, 3706 Bundle.getMessage("InfoMessage5", 3707 new Object[]{block.getUserName()}), 3708 Bundle.getMessage("MessageTitle"), 3709 JmriJOptionPane.INFORMATION_MESSAGE); 3710 return; 3711 } 3712 if (!initializeBlockBossLogic(head.getDisplayName())) { 3713 return; 3714 } 3715 logic.setMode(BlockBossLogic.TRAILINGMAIN); 3716 logic.setTurnout(turnout.getDisplayName()); 3717 logic.setSensor1(occupancy.getDisplayName()); 3718 if (nextHead != null) { 3719 logic.setWatchedSignal1(nextHead.getDisplayName(), false); 3720 } 3721 if (auxSignal != null) { 3722 logic.setWatchedSignal1Alt(auxSignal.getDisplayName()); 3723 } 3724 finalizeBlockBossLogic(); 3725 } //setLogicXoverContinuing 3726 3727 /*=======================*\ 3728 |* setSignalsAtLevelXing *| 3729 \*=======================*/ 3730 /** 3731 * Tool to set signals at a level crossing, including placing the signal 3732 * icons and setup of Simple Signal Logic for each signal head 3733 * <p> 3734 * This tool assumes left facing signal head icons have been selected, and 3735 * will rotate the signal head icons accordingly. 3736 * <p> 3737 * This tool will place icons on the right side of each track. 3738 * <p> 3739 * Both tracks do not need to be signalled. If one signal for a track, A-C 3740 * or B-D, the other must also be present. 3741 * <p> 3742 * Some user adjustment of turnout positions may be needed. 3743 */ 3744 //operational variables for Set Signals at Level Crossing tool 3745 private JmriJFrame setSignalsAtLevelXingFrame = null; 3746 private boolean setSignalsAtLevelXingOpenFlag = false; 3747 private boolean setSignalsAtLevelXingFromMenuFlag = false; 3748 3749 private JLabel blockACNameLabel = null; 3750 private JLabel blockBDNameLabel = null; 3751 3752 private final NamedBeanComboBox<Block> blockACComboBox = new NamedBeanComboBox<>( 3753 InstanceManager.getDefault(BlockManager.class), 3754 null, DisplayOptions.DISPLAYNAME); 3755 private final NamedBeanComboBox<Block> blockBDComboBox = new NamedBeanComboBox<>( 3756 InstanceManager.getDefault(BlockManager.class), 3757 null, DisplayOptions.DISPLAYNAME); 3758 3759 private final NamedBeanComboBox<SignalHead> aSignalHeadComboBox = new NamedBeanComboBox<>( 3760 InstanceManager.getDefault(SignalHeadManager.class), 3761 null, DisplayOptions.DISPLAYNAME); 3762 private final NamedBeanComboBox<SignalHead> bSignalHeadComboBox = new NamedBeanComboBox<>( 3763 InstanceManager.getDefault(SignalHeadManager.class), 3764 null, DisplayOptions.DISPLAYNAME); 3765 private final NamedBeanComboBox<SignalHead> cSignalHeadComboBox = new NamedBeanComboBox<>( 3766 InstanceManager.getDefault(SignalHeadManager.class), 3767 null, DisplayOptions.DISPLAYNAME); 3768 private final NamedBeanComboBox<SignalHead> dSignalHeadComboBox = new NamedBeanComboBox<>( 3769 InstanceManager.getDefault(SignalHeadManager.class), 3770 null, DisplayOptions.DISPLAYNAME); 3771 3772 private final JCheckBox setAHead = new JCheckBox(Bundle.getMessage("PlaceHead")); 3773 private final JCheckBox setBHead = new JCheckBox(Bundle.getMessage("PlaceHead")); 3774 private final JCheckBox setCHead = new JCheckBox(Bundle.getMessage("PlaceHead")); 3775 private final JCheckBox setDHead = new JCheckBox(Bundle.getMessage("PlaceHead")); 3776 3777 private final JCheckBox setupALogic = new JCheckBox(Bundle.getMessage("SetLogic")); 3778 private final JCheckBox setupBLogic = new JCheckBox(Bundle.getMessage("SetLogic")); 3779 private final JCheckBox setupCLogic = new JCheckBox(Bundle.getMessage("SetLogic")); 3780 private final JCheckBox setupDLogic = new JCheckBox(Bundle.getMessage("SetLogic")); 3781 3782 private JButton getSavedXingSignalHeads = null; 3783 private JButton changeXingSignalIcon = null; 3784 private JButton setXingSignalsDone = null; 3785 private JButton setXingSignalsCancel = null; 3786 3787 private LevelXing levelXing = null; 3788 3789 private SignalHead aHead = null; 3790 private SignalHead bHead = null; 3791 private SignalHead cHead = null; 3792 private SignalHead dHead = null; 3793 3794 //display dialog for Set Signals at Level Crossing tool 3795 public void setSignalsAtLevelXingFromMenu(@Nonnull LevelXing xing, 3796 @Nonnull MultiIconEditor theEditor, 3797 @Nonnull JFrame theFrame) { 3798 levelXing = xing; 3799 blockACComboBox.setSelectedItem(levelXing.getLayoutBlockAC().getBlock()); 3800 blockBDComboBox.setSelectedItem(levelXing.getLayoutBlockBD().getBlock()); 3801 setSignalsAtLevelXingFromMenuFlag = true; 3802 setSignalsAtLevelXing(theEditor, theFrame); 3803 setSignalsAtLevelXingFromMenuFlag = false; 3804 } 3805 3806 public void setSignalsAtLevelXing(@Nonnull MultiIconEditor theEditor, 3807 @Nonnull JFrame theFrame) { 3808 signalIconEditor = theEditor; 3809 signalFrame = theFrame; 3810 3811 //Initialize if needed 3812 if (setSignalsAtLevelXingFrame == null) { 3813 setSignalsAtLevelXingOpenFlag = false; 3814 setSignalsAtLevelXingFrame = new JmriJFrame(Bundle.getMessage("SignalsAtLevelXing"), false, true); 3815 oneFrameToRuleThemAll(setSignalsAtLevelXingFrame); 3816 setSignalsAtLevelXingFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 3817 setSignalsAtLevelXingFrame.addHelpMenu("package.jmri.jmrit.display.SetSignalsAtLevelXing", true); 3818 setSignalsAtLevelXingFrame.setLocation(70, 30); 3819 Container theContentPane = setSignalsAtLevelXingFrame.getContentPane(); 3820 theContentPane.setLayout(new BoxLayout(theContentPane, BoxLayout.Y_AXIS)); 3821 3822 JPanel panel11 = new JPanel(new FlowLayout()); 3823 blockACNameLabel = new JLabel(Bundle.getMessage("MakeLabel", (Bundle.getMessage("BeanNameBlock") + " AC"))); 3824 panel11.add(blockACNameLabel); 3825 panel11.add(blockACComboBox); 3826 blockACComboBox.setToolTipText(Bundle.getMessage("SignalsBlockNameHint")); 3827 theContentPane.add(panel11); 3828 3829 JPanel panel12 = new JPanel(new FlowLayout()); 3830 blockBDNameLabel = new JLabel(Bundle.getMessage("MakeLabel", (Bundle.getMessage("BeanNameBlock") + " BD"))); 3831 panel12.add(blockBDNameLabel); 3832 panel12.add(blockBDComboBox); 3833 blockBDComboBox.setToolTipText(Bundle.getMessage("SignalsBlockNameHint")); 3834 3835 theContentPane.add(panel12); 3836 theContentPane.add(new JSeparator(JSeparator.HORIZONTAL)); 3837 3838 JPanel panel2 = new JPanel(new FlowLayout()); 3839 JLabel shTitle = new JLabel(Bundle.getMessage("SignalHeads")); 3840 panel2.add(shTitle); 3841 panel2.add(new JLabel(" ")); 3842 panel2.add(getSavedXingSignalHeads = new JButton(Bundle.getMessage("GetSaved"))); 3843 getSavedXingSignalHeads.addActionListener(this::xingSignalsGetSaved); 3844 getSavedXingSignalHeads.setToolTipText(Bundle.getMessage("GetSavedHint")); 3845 theContentPane.add(panel2); 3846 3847 theContentPane.add(new JSeparator(JSeparator.HORIZONTAL)); 3848 JPanel panel2a = new JPanel(new FlowLayout()); 3849 panel2a.add(new JLabel(" ")); 3850 panel2a.add(setPlaceAllHeads); 3851 setPlaceAllHeads.setToolTipText(Bundle.getMessage("PlaceAllHeadsHint")); 3852 setPlaceAllHeads.addActionListener((ActionEvent e) -> { 3853 boolean isSelected = setPlaceAllHeads.isSelected(); 3854 //(de)select all checkboxes 3855 setAHead.setSelected(isSelected); 3856 setBHead.setSelected(isSelected); 3857 setCHead.setSelected(isSelected); 3858 setDHead.setSelected(isSelected); 3859 }); 3860 panel2a.add(new JLabel(" ")); 3861 panel2a.add(setupAllLogic); 3862 setupAllLogic.setToolTipText(Bundle.getMessage("SetAllLogicHint")); 3863 setupAllLogic.addActionListener((ActionEvent e) -> { 3864 boolean isSelected = setupAllLogic.isSelected(); 3865 //(de)select all checkboxes 3866 setupALogic.setSelected(isSelected); 3867 setupBLogic.setSelected(isSelected); 3868 setupCLogic.setSelected(isSelected); 3869 setupDLogic.setSelected(isSelected); 3870 }); 3871 theContentPane.add(panel2a); 3872 3873 JPanel panel21 = new JPanel(new FlowLayout()); 3874 JLabel aLabel = new JLabel(Bundle.getMessage("MakeLabel", 3875 Bundle.getMessage("TrackXConnect", "A"))); 3876 panel21.add(aLabel); 3877 panel21.add(aSignalHeadComboBox); 3878 theContentPane.add(panel21); 3879 aSignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 3880 3881 JPanel panel22 = new JPanel(new FlowLayout()); 3882 panel22.add(new JLabel(" ")); 3883 panel22.add(setAHead); 3884 setAHead.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 3885 panel22.add(new JLabel(" ")); 3886 panel22.add(setupALogic); 3887 setupALogic.setToolTipText(Bundle.getMessage("SetLogicHint")); 3888 theContentPane.add(panel22); 3889 3890 JPanel panel31 = new JPanel(new FlowLayout()); 3891 JLabel bLabel = new JLabel(Bundle.getMessage("MakeLabel", 3892 Bundle.getMessage("TrackXConnect", "B"))); 3893 panel31.add(bLabel); 3894 panel31.add(bSignalHeadComboBox); 3895 theContentPane.add(panel31); 3896 bSignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 3897 3898 JPanel panel32 = new JPanel(new FlowLayout()); 3899 panel32.add(new JLabel(" ")); 3900 panel32.add(setBHead); 3901 setBHead.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 3902 panel32.add(new JLabel(" ")); 3903 panel32.add(setupBLogic); 3904 setupBLogic.setToolTipText(Bundle.getMessage("SetLogicHint")); 3905 theContentPane.add(panel32); 3906 3907 JPanel panel41 = new JPanel(new FlowLayout()); 3908 JLabel cLabel = new JLabel(Bundle.getMessage("MakeLabel", 3909 Bundle.getMessage("TrackXConnect", "C"))); 3910 panel41.add(cLabel); 3911 panel41.add(cSignalHeadComboBox); 3912 theContentPane.add(panel41); 3913 cSignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 3914 3915 JPanel panel42 = new JPanel(new FlowLayout()); 3916 panel42.add(new JLabel(" ")); 3917 panel42.add(setCHead); 3918 setCHead.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 3919 panel42.add(new JLabel(" ")); 3920 panel42.add(setupCLogic); 3921 setupCLogic.setToolTipText(Bundle.getMessage("SetLogicHint")); 3922 theContentPane.add(panel42); 3923 3924 JPanel panel51 = new JPanel(new FlowLayout()); 3925 JLabel dLabel = new JLabel(Bundle.getMessage("MakeLabel", 3926 Bundle.getMessage("TrackXConnect", "D"))); 3927 panel51.add(dLabel); 3928 panel51.add(dSignalHeadComboBox); 3929 theContentPane.add(panel51); 3930 dSignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 3931 3932 JPanel panel52 = new JPanel(new FlowLayout()); 3933 panel52.add(new JLabel(" ")); 3934 panel52.add(setDHead); 3935 setDHead.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 3936 panel52.add(new JLabel(" ")); 3937 panel52.add(setupDLogic); 3938 setupDLogic.setToolTipText(Bundle.getMessage("SetLogicHint")); 3939 theContentPane.add(panel52); 3940 theContentPane.add(new JSeparator(JSeparator.HORIZONTAL)); 3941 3942 JPanel panel6 = new JPanel(new FlowLayout()); 3943 panel6.add(changeXingSignalIcon = new JButton(Bundle.getMessage("ChangeSignalIcon"))); 3944 changeXingSignalIcon.addActionListener((ActionEvent e) -> signalFrame.setVisible(true)); 3945 changeXingSignalIcon.setToolTipText(Bundle.getMessage("ChangeSignalIconHint")); 3946 panel6.add(new JLabel(" ")); 3947 panel6.add(setXingSignalsDone = new JButton(Bundle.getMessage("ButtonDone"))); 3948 setXingSignalsDone.addActionListener(this::setXingSignalsDonePressed); 3949 setXingSignalsDone.setToolTipText(Bundle.getMessage("DoneHint", Bundle.getMessage("ButtonDone"))); 3950 3951 panel6.add(setXingSignalsCancel = new JButton(Bundle.getMessage("ButtonCancel"))); 3952 setXingSignalsCancel.addActionListener(this::setXingSignalsCancelPressed); 3953 setXingSignalsCancel.setToolTipText(Bundle.getMessage("CancelHint", Bundle.getMessage("ButtonCancel"))); 3954 theContentPane.add(panel6); 3955 3956 //make this button the default button (return or enter activates) 3957 JRootPane rootPane = SwingUtilities.getRootPane(setXingSignalsDone); 3958 if (rootPane != null) { 3959 rootPane.setDefaultButton(setXingSignalsDone); 3960 } 3961 3962 setSignalsAtLevelXingFrame.addWindowListener(new WindowAdapter() { 3963 @Override 3964 public void windowClosing(WindowEvent e) { 3965 setXingSignalsCancelPressed(null); 3966 } 3967 }); 3968 } 3969 3970 aSignalHeadComboBox.setSelectedItem(null); 3971 bSignalHeadComboBox.setSelectedItem(null); 3972 cSignalHeadComboBox.setSelectedItem(null); 3973 dSignalHeadComboBox.setSelectedItem(null); 3974 3975 setPlaceAllHeads.setSelected(false); 3976 setupAllLogic.setSelected(false); 3977 3978 blockACComboBox.setVisible(!setSignalsAtLevelXingFromMenuFlag); 3979 blockBDComboBox.setVisible(!setSignalsAtLevelXingFromMenuFlag); 3980 3981 if (setSignalsAtLevelXingFromMenuFlag) { 3982 blockACNameLabel.setText(Bundle.getMessage("MakeLabel", 3983 (Bundle.getMessage("BeanNameBlock") + " AC")) 3984 + levelXing.getBlockNameAC()); 3985 blockBDNameLabel.setText(Bundle.getMessage("MakeLabel", 3986 (Bundle.getMessage("BeanNameBlock") + " BD")) 3987 + levelXing.getBlockNameBD()); 3988 xingSignalsGetSaved(null); 3989 } else { 3990 blockACNameLabel.setText(Bundle.getMessage("MakeLabel", (Bundle.getMessage("BeanNameBlock") + " AC"))); 3991 blockBDNameLabel.setText(Bundle.getMessage("MakeLabel", (Bundle.getMessage("BeanNameBlock") + " BD"))); 3992 } 3993 3994 if (!setSignalsAtLevelXingOpenFlag) { 3995 setSignalsAtLevelXingFrame.setPreferredSize(null); 3996 setSignalsAtLevelXingFrame.pack(); 3997 setSignalsAtLevelXingOpenFlag = true; 3998 } 3999 4000 setSignalsAtLevelXingFrame.setVisible(true); 4001 } //setSignalsAtLevelXing 4002 4003 private void xingSignalsGetSaved(ActionEvent a) { 4004 if (!getLevelCrossingInformation()) { 4005 return; 4006 } 4007 aSignalHeadComboBox.setSelectedItem(levelXing.getSignalHead(LevelXing.Geometry.POINTA)); 4008 bSignalHeadComboBox.setSelectedItem(levelXing.getSignalHead(LevelXing.Geometry.POINTB)); 4009 cSignalHeadComboBox.setSelectedItem(levelXing.getSignalHead(LevelXing.Geometry.POINTC)); 4010 dSignalHeadComboBox.setSelectedItem(levelXing.getSignalHead(LevelXing.Geometry.POINTD)); 4011 } 4012 4013 private void setXingSignalsCancelPressed(ActionEvent a) { 4014 setSignalsAtLevelXingOpenFlag = false; 4015 setSignalsAtLevelXingFrame.setVisible(false); 4016 } 4017 4018 private void setXingSignalsDonePressed(ActionEvent a) { 4019 if (!getLevelCrossingInformation()) { 4020 return; 4021 } 4022 if (!getXingSignalHeadInformation()) { 4023 return; 4024 } 4025 4026 //place or update signals as requested 4027 String signalName = aSignalHeadComboBox.getSelectedItemDisplayName(); 4028 if (signalName == null) { 4029 signalName = ""; 4030 } 4031 if ((aHead != null) && setAHead.isSelected()) { 4032 if (isHeadOnPanel(aHead) 4033 && (aHead != getHeadFromName(levelXing.getSignalAName()))) { 4034 JmriJOptionPane.showMessageDialog(setSignalsAtLevelXingFrame, 4035 Bundle.getMessage("SignalsError6", 4036 new Object[]{signalName}), 4037 Bundle.getMessage("ErrorTitle"), 4038 JmriJOptionPane.ERROR_MESSAGE); 4039 return; 4040 } else { 4041 removeSignalHeadFromPanel(levelXing.getSignalAName()); 4042 placeXingA(); 4043 removeAssignment(aHead); 4044 levelXing.setSignalAName(signalName); 4045 needRedraw = true; 4046 } 4047 } else if ((aHead != null) 4048 && (aHead != getHeadFromName(levelXing.getSignalAName())) 4049 && (aHead != getHeadFromName(levelXing.getSignalBName())) 4050 && (aHead != getHeadFromName(levelXing.getSignalCName())) 4051 && (aHead != getHeadFromName(levelXing.getSignalDName()))) { 4052 if (isHeadOnPanel(aHead)) { 4053 JmriJOptionPane.showMessageDialog(setSignalsAtLevelXingFrame, 4054 Bundle.getMessage("SignalsError13", 4055 new Object[]{signalName}), 4056 Bundle.getMessage("ErrorTitle"), 4057 JmriJOptionPane.ERROR_MESSAGE); 4058 return; 4059 } else { 4060 removeSignalHeadFromPanel(levelXing.getSignalAName()); 4061 removeAssignment(aHead); 4062 levelXing.setSignalAName(signalName); 4063 } 4064 } else if ((aHead != null) 4065 && ((aHead == getHeadFromName(levelXing.getSignalBName())) 4066 || (aHead == getHeadFromName(levelXing.getSignalCName())) 4067 || (aHead == getHeadFromName(levelXing.getSignalDName())))) { 4068 //need to figure out what to do in this case. 4069 log.trace("need to figure out what to do in this case."); 4070 } else if (aHead == null) { 4071 removeSignalHeadFromPanel(levelXing.getSignalAName()); 4072 levelXing.setSignalAName(""); 4073 } 4074 signalName = bSignalHeadComboBox.getSelectedItemDisplayName(); 4075 if (signalName == null) { 4076 signalName = ""; 4077 } 4078 if ((bHead != null) && setBHead.isSelected()) { 4079 if (isHeadOnPanel(bHead) 4080 && (bHead != getHeadFromName(levelXing.getSignalBName()))) { 4081 JmriJOptionPane.showMessageDialog(setSignalsAtLevelXingFrame, 4082 Bundle.getMessage("SignalsError6", 4083 new Object[]{signalName}), 4084 Bundle.getMessage("ErrorTitle"), 4085 JmriJOptionPane.ERROR_MESSAGE); 4086 return; 4087 } else { 4088 removeSignalHeadFromPanel(levelXing.getSignalBName()); 4089 placeXingB(); 4090 removeAssignment(bHead); 4091 levelXing.setSignalBName(signalName); 4092 needRedraw = true; 4093 } 4094 } else if ((bHead != null) 4095 && (bHead != getHeadFromName(levelXing.getSignalAName())) 4096 && (bHead != getHeadFromName(levelXing.getSignalBName())) 4097 && (bHead != getHeadFromName(levelXing.getSignalCName())) 4098 && (bHead != getHeadFromName(levelXing.getSignalDName()))) { 4099 if (isHeadOnPanel(bHead)) { 4100 JmriJOptionPane.showMessageDialog(setSignalsAtLevelXingFrame, 4101 Bundle.getMessage("SignalsError13", 4102 new Object[]{signalName}), 4103 Bundle.getMessage("ErrorTitle"), 4104 JmriJOptionPane.ERROR_MESSAGE); 4105 return; 4106 } else { 4107 removeSignalHeadFromPanel(levelXing.getSignalBName()); 4108 removeAssignment(bHead); 4109 levelXing.setSignalBName(signalName); 4110 } 4111 } else if ((bHead != null) 4112 && ((bHead == getHeadFromName(levelXing.getSignalAName())) 4113 || (bHead == getHeadFromName(levelXing.getSignalCName())) 4114 || (bHead == getHeadFromName(levelXing.getSignalDName())))) { 4115 //need to figure out what to do in this case. 4116 log.trace("need to figure out what to do in this case."); 4117 } else if (bHead == null) { 4118 removeSignalHeadFromPanel(levelXing.getSignalBName()); 4119 levelXing.setSignalBName(""); 4120 } 4121 signalName = cSignalHeadComboBox.getSelectedItemDisplayName(); 4122 if (signalName == null) { 4123 signalName = ""; 4124 } 4125 if ((cHead != null) && setCHead.isSelected()) { 4126 if (isHeadOnPanel(cHead) 4127 && (cHead != getHeadFromName(levelXing.getSignalCName()))) { 4128 JmriJOptionPane.showMessageDialog(setSignalsAtLevelXingFrame, 4129 Bundle.getMessage("SignalsError6", 4130 new Object[]{signalName}), 4131 Bundle.getMessage("ErrorTitle"), 4132 JmriJOptionPane.ERROR_MESSAGE); 4133 return; 4134 } else { 4135 removeSignalHeadFromPanel(levelXing.getSignalCName()); 4136 placeXingC(); 4137 removeAssignment(cHead); 4138 levelXing.setSignalCName(signalName); 4139 needRedraw = true; 4140 } 4141 } else if ((cHead != null) 4142 && (cHead != getHeadFromName(levelXing.getSignalAName())) 4143 && (cHead != getHeadFromName(levelXing.getSignalBName())) 4144 && (cHead != getHeadFromName(levelXing.getSignalCName())) 4145 && (cHead != getHeadFromName(levelXing.getSignalDName()))) { 4146 if (isHeadOnPanel(cHead)) { 4147 JmriJOptionPane.showMessageDialog(setSignalsAtLevelXingFrame, 4148 Bundle.getMessage("SignalsError13", 4149 new Object[]{signalName}), 4150 Bundle.getMessage("ErrorTitle"), 4151 JmriJOptionPane.ERROR_MESSAGE); 4152 return; 4153 } else { 4154 removeSignalHeadFromPanel(levelXing.getSignalCName()); 4155 removeAssignment(cHead); 4156 levelXing.setSignalCName(signalName); 4157 } 4158 } else if ((cHead != null) 4159 && ((cHead == getHeadFromName(levelXing.getSignalBName())) 4160 || (cHead == getHeadFromName(levelXing.getSignalAName())) 4161 || (cHead == getHeadFromName(levelXing.getSignalDName())))) { 4162 //need to figure out what to do in this case. 4163 log.trace("need to figure out what to do in this case."); 4164 } else if (cHead == null) { 4165 removeSignalHeadFromPanel(levelXing.getSignalCName()); 4166 levelXing.setSignalCName(""); 4167 } 4168 signalName = dSignalHeadComboBox.getSelectedItemDisplayName(); 4169 if (signalName == null) { 4170 signalName = ""; 4171 } 4172 if ((dHead != null) && setDHead.isSelected()) { 4173 if (isHeadOnPanel(dHead) 4174 && (dHead != getHeadFromName(levelXing.getSignalDName()))) { 4175 JmriJOptionPane.showMessageDialog(setSignalsAtLevelXingFrame, 4176 Bundle.getMessage("SignalsError6", 4177 new Object[]{signalName}), 4178 Bundle.getMessage("ErrorTitle"), 4179 JmriJOptionPane.ERROR_MESSAGE); 4180 return; 4181 } else { 4182 removeSignalHeadFromPanel(levelXing.getSignalDName()); 4183 placeXingD(); 4184 removeAssignment(dHead); 4185 levelXing.setSignalDName(signalName); 4186 needRedraw = true; 4187 } 4188 } else if ((dHead != null) 4189 && (dHead != getHeadFromName(levelXing.getSignalAName())) 4190 && (dHead != getHeadFromName(levelXing.getSignalBName())) 4191 && (dHead != getHeadFromName(levelXing.getSignalCName())) 4192 && (dHead != getHeadFromName(levelXing.getSignalDName()))) { 4193 if (isHeadOnPanel(dHead)) { 4194 JmriJOptionPane.showMessageDialog(setSignalsAtLevelXingFrame, 4195 Bundle.getMessage("SignalsError13", 4196 new Object[]{signalName}), 4197 Bundle.getMessage("ErrorTitle"), 4198 JmriJOptionPane.ERROR_MESSAGE); 4199 return; 4200 } else { 4201 removeSignalHeadFromPanel(levelXing.getSignalDName()); 4202 removeAssignment(dHead); 4203 levelXing.setSignalDName(signalName); 4204 } 4205 } else if ((dHead != null) 4206 && ((dHead == getHeadFromName(levelXing.getSignalBName())) 4207 || (dHead == getHeadFromName(levelXing.getSignalCName())) 4208 || (dHead == getHeadFromName(levelXing.getSignalAName())))) { 4209 //need to figure out what to do in this case. 4210 log.trace("need to figure out what to do in this case."); 4211 } else if (dHead == null) { 4212 removeSignalHeadFromPanel(levelXing.getSignalDName()); 4213 levelXing.setSignalDName(""); 4214 } 4215 //setup logic if requested 4216 if (setupALogic.isSelected() && (aHead != null)) { 4217 setLogicXing(aHead, (TrackSegment) levelXing.getConnectC(), 4218 levelXing.getLayoutBlockBD(), (TrackSegment) levelXing.getConnectB(), 4219 (TrackSegment) levelXing.getConnectD(), aSignalHeadComboBox.getSelectedItemDisplayName()); 4220 } 4221 if (setupBLogic.isSelected() && (bHead != null)) { 4222 setLogicXing(bHead, (TrackSegment) levelXing.getConnectD(), 4223 levelXing.getLayoutBlockAC(), (TrackSegment) levelXing.getConnectA(), 4224 (TrackSegment) levelXing.getConnectC(), bSignalHeadComboBox.getSelectedItemDisplayName()); 4225 } 4226 if (setupCLogic.isSelected() && (cHead != null)) { 4227 setLogicXing(cHead, (TrackSegment) levelXing.getConnectA(), 4228 levelXing.getLayoutBlockBD(), (TrackSegment) levelXing.getConnectB(), 4229 (TrackSegment) levelXing.getConnectD(), cSignalHeadComboBox.getSelectedItemDisplayName()); 4230 } 4231 if (setupDLogic.isSelected() && (dHead != null)) { 4232 setLogicXing(dHead, (TrackSegment) levelXing.getConnectB(), 4233 levelXing.getLayoutBlockAC(), (TrackSegment) levelXing.getConnectA(), 4234 (TrackSegment) levelXing.getConnectC(), dSignalHeadComboBox.getSelectedItemDisplayName()); 4235 } 4236 //finish up 4237 setSignalsAtLevelXingOpenFlag = false; 4238 setSignalsAtLevelXingFrame.setVisible(false); 4239 if (needRedraw) { 4240 layoutEditor.redrawPanel(); 4241 needRedraw = false; 4242 layoutEditor.setDirty(); 4243 } 4244 } //setXingSignalsDonePressed 4245 4246 private boolean getLevelCrossingInformation() { 4247 if (!setSignalsAtLevelXingFromMenuFlag) { 4248 levelXing = null; 4249 List<LevelXing> levelXings = layoutEditor.getLevelXings(); 4250 if (levelXings.size() <= 0) { 4251 JmriJOptionPane.showMessageDialog(setSignalsAtLevelXingFrame, 4252 Bundle.getMessage("SignalsError15"), 4253 Bundle.getMessage("ErrorTitle"), 4254 JmriJOptionPane.ERROR_MESSAGE); 4255 return false; 4256 } else if (levelXings.size() == 1) { 4257 levelXing = levelXings.get(0); 4258 } else { 4259 LayoutBlock xingBlockA = null; 4260 xingBlockA = getBlockFromEntry(blockACComboBox); 4261 if (xingBlockA == null) { 4262 return false; 4263 } 4264 4265 LayoutBlock xingBlockC = getBlockFromEntry(blockBDComboBox); 4266 if (xingBlockC == null) { 4267 return false; 4268 } 4269 4270 int foundCount = 0; 4271 //make two block tests first 4272 for (LevelXing x : layoutEditor.getLevelXings()) { 4273 LayoutBlock xA = null; 4274 LayoutBlock xB = null; 4275 LayoutBlock xC = null; 4276 LayoutBlock xD = null; 4277 LayoutBlock xAC = x.getLayoutBlockAC(); 4278 LayoutBlock xBD = x.getLayoutBlockBD(); 4279 if (x.getConnectA() != null) { 4280 xA = ((TrackSegment) x.getConnectA()).getLayoutBlock(); 4281 } 4282 if (x.getConnectB() != null) { 4283 xB = ((TrackSegment) x.getConnectB()).getLayoutBlock(); 4284 } 4285 if (x.getConnectC() != null) { 4286 xC = ((TrackSegment) x.getConnectC()).getLayoutBlock(); 4287 } 4288 if (x.getConnectD() != null) { 4289 xD = ((TrackSegment) x.getConnectD()).getLayoutBlock(); 4290 } 4291 if (((xA != null) && (xC != null) && (((xA == xingBlockA) && (xC == xingBlockC)) 4292 || ((xA == xingBlockC) && (xC == xingBlockA)))) 4293 || ((xB != null) && (xD != null) && (((xB == xingBlockA) && (xD == xingBlockC)) 4294 || ((xB == xingBlockC) && (xD == xingBlockA))))) { 4295 levelXing = x; 4296 foundCount++; 4297 } else if ((xAC != null) && (xBD != null) && (((xAC == xingBlockA) && (xBD == xingBlockC)) 4298 || ((xAC == xingBlockC) && (xBD == xingBlockA)))) { 4299 levelXing = x; 4300 foundCount++; 4301 } 4302 } 4303 if (foundCount == 0) { 4304 //try one block test 4305 for (LevelXing x : layoutEditor.getLevelXings()) { 4306 if ((xingBlockA == x.getLayoutBlockAC()) || (xingBlockA == x.getLayoutBlockBD())) { 4307 levelXing = x; 4308 foundCount++; 4309 } 4310 } 4311 } 4312 if (foundCount > 1) { 4313 JmriJOptionPane.showMessageDialog(setSignalsAtLevelXingFrame, 4314 Bundle.getMessage("SignalsError16", 4315 new Object[]{" " + foundCount + " "}), 4316 Bundle.getMessage("ErrorTitle"), 4317 JmriJOptionPane.ERROR_MESSAGE); 4318 return false; 4319 } 4320 if (levelXing == null) { 4321 JmriJOptionPane.showMessageDialog(setSignalsAtLevelXingFrame, 4322 Bundle.getMessage("SignalsError17"), 4323 Bundle.getMessage("ErrorTitle"), 4324 JmriJOptionPane.ERROR_MESSAGE); 4325 return false; 4326 } 4327 } 4328 } 4329 4330 LevelXingView levelXingView = layoutEditor.getLevelXingView(levelXing); 4331 4332 Point2D coordsA = levelXingView.getCoordsA(); 4333 Point2D coordsC = levelXingView.getCoordsC(); 4334 placeSignalDirectionDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsC, coordsA)); 4335 4336 return true; 4337 } //getLevelCrossingInformation 4338 4339 private boolean getXingSignalHeadInformation() { 4340 //note that all heads are optional, but pairs must be present 4341 aHead = getSignalHeadFromEntry(aSignalHeadComboBox, false, setSignalsAtLevelXingFrame); 4342 bHead = getSignalHeadFromEntry(bSignalHeadComboBox, false, setSignalsAtLevelXingFrame); 4343 cHead = getSignalHeadFromEntry(cSignalHeadComboBox, false, setSignalsAtLevelXingFrame); 4344 dHead = getSignalHeadFromEntry(dSignalHeadComboBox, false, setSignalsAtLevelXingFrame); 4345 if (((aHead != null) && (cHead == null)) || ((aHead == null) && (cHead != null)) 4346 || ((bHead != null) && (dHead == null)) || ((bHead == null) && (dHead != null))) { 4347 JmriJOptionPane.showMessageDialog(setSignalsAtLevelXingFrame, 4348 Bundle.getMessage("SignalsError14"), 4349 Bundle.getMessage("ErrorTitle"), 4350 JmriJOptionPane.ERROR_MESSAGE); 4351 return false; 4352 } 4353 if ((aHead == null) && (bHead == null) && (cHead == null) && (dHead == null)) { 4354 JmriJOptionPane.showMessageDialog(setSignalsAtLevelXingFrame, 4355 Bundle.getMessage("SignalsError12"), 4356 Bundle.getMessage("ErrorTitle"), 4357 JmriJOptionPane.ERROR_MESSAGE); 4358 return false; 4359 } 4360 return true; 4361 } 4362 4363 private void placeXingA() { 4364 if (testIcon == null) { 4365 testIcon = signalIconEditor.getIcon(0); 4366 } 4367 String signalHeadName = aSignalHeadComboBox.getSelectedItemDisplayName(); 4368 if (signalHeadName == null) { 4369 signalHeadName = ""; 4370 } 4371 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 4372 4373 LevelXingView levelXingView = layoutEditor.getLevelXingView(levelXing); 4374 4375 Point2D coordsA = levelXingView.getCoordsA(); 4376 Point2D delta = new Point2D.Double(0.0, +shift); 4377 4378 delta = MathUtil.rotateDEG(delta, placeSignalDirectionDEG); 4379 Point2D where = MathUtil.add(coordsA, delta); 4380 setSignalHeadOnPanel(placeSignalDirectionDEG + 180.0, signalHeadName, where); 4381 } 4382 4383 private void placeXingB() { 4384 if (testIcon == null) { 4385 testIcon = signalIconEditor.getIcon(0); 4386 } 4387 String signalHeadName = bSignalHeadComboBox.getSelectedItemDisplayName(); 4388 if (signalHeadName == null) { 4389 signalHeadName = ""; 4390 } 4391 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 4392 4393 LevelXingView levelXingView = layoutEditor.getLevelXingView(levelXing); 4394 4395 Point2D coordsB = levelXingView.getCoordsB(); 4396 Point2D coordsD = levelXingView.getCoordsD(); 4397 4398 double directionDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsB, coordsD)); 4399 Point2D delta = new Point2D.Double(0.0, -shift); 4400 4401 delta = MathUtil.rotateDEG(delta, directionDEG); 4402 Point2D where = MathUtil.add(coordsB, delta); 4403 setSignalHeadOnPanel(directionDEG, signalHeadName, where); 4404 } 4405 4406 private void placeXingC() { 4407 if (testIcon == null) { 4408 testIcon = signalIconEditor.getIcon(0); 4409 } 4410 String signalHeadName = cSignalHeadComboBox.getSelectedItemDisplayName(); 4411 if (signalHeadName == null) { 4412 signalHeadName = ""; 4413 } 4414 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 4415 4416 LevelXingView levelXingView = layoutEditor.getLevelXingView(levelXing); 4417 4418 Point2D coordsC = levelXingView.getCoordsC(); 4419 Point2D delta = new Point2D.Double(0.0, -shift); 4420 4421 delta = MathUtil.rotateDEG(delta, placeSignalDirectionDEG); 4422 Point2D where = MathUtil.add(coordsC, delta); 4423 setSignalHeadOnPanel(placeSignalDirectionDEG, signalHeadName, where); 4424 } 4425 4426 private void placeXingD() { 4427 if (testIcon == null) { 4428 testIcon = signalIconEditor.getIcon(0); 4429 } 4430 String signalHeadName = dSignalHeadComboBox.getSelectedItemDisplayName(); 4431 if (signalHeadName == null) { 4432 signalHeadName = ""; 4433 } 4434 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 4435 4436 LevelXingView levelXingView = layoutEditor.getLevelXingView(levelXing); 4437 4438 Point2D coordsB = levelXingView.getCoordsB(); 4439 Point2D coordsD = levelXingView.getCoordsD(); 4440 4441 double directionDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsD, coordsB)); 4442 double diffDirDEG = MathUtil.diffAngleDEG(placeSignalDirectionDEG, directionDEG + 180.0); 4443 Point2D delta = new Point2D.Double(-shift * Math.cos(Math.toRadians(diffDirDEG)), -shift); 4444 4445 delta = MathUtil.rotateDEG(delta, directionDEG); 4446 Point2D where = MathUtil.add(coordsD, delta); 4447 setSignalHeadOnPanel(directionDEG, signalHeadName, where); 4448 } 4449 4450 @SuppressWarnings("null") 4451 private void setLogicXing(SignalHead head, TrackSegment track, LayoutBlock crossBlock, 4452 TrackSegment crossTrack1, TrackSegment crossTrack2, String signalHeadName) { 4453 if (track == null) { 4454 JmriJOptionPane.showMessageDialog(setSignalsAtLevelXingFrame, 4455 Bundle.getMessage("InfoMessage7"), 4456 Bundle.getMessage("MessageTitle"), 4457 JmriJOptionPane.INFORMATION_MESSAGE); 4458 return; 4459 } 4460 Sensor occupancy = null; 4461 Sensor crossOccupancy = null; 4462 Sensor track1Occupancy = null; 4463 Sensor track2Occupancy = null; 4464 SignalHead nextHead = null; 4465 LayoutBlock block = track.getLayoutBlock(); 4466 if (block == null) { 4467 JmriJOptionPane.showMessageDialog(setSignalsAtLevelXingFrame, 4468 Bundle.getMessage("InfoMessage6"), 4469 Bundle.getMessage("MessageTitle"), 4470 JmriJOptionPane.INFORMATION_MESSAGE); 4471 return; 4472 } 4473 occupancy = block.getOccupancySensor(); 4474 if (occupancy == null) { 4475 JmriJOptionPane.showMessageDialog(setSignalsAtLevelXingFrame, 4476 Bundle.getMessage("InfoMessage4", 4477 new Object[]{block.getUserName()}), 4478 Bundle.getMessage("MessageTitle"), 4479 JmriJOptionPane.INFORMATION_MESSAGE); 4480 return; 4481 } 4482 if (crossBlock != null) { 4483 crossOccupancy = crossBlock.getOccupancySensor(); 4484 } 4485 if (crossTrack1 != null) { 4486 block = crossTrack1.getLayoutBlock(); 4487 if (block != null) { 4488 track1Occupancy = block.getOccupancySensor(); 4489 if (track1Occupancy == crossOccupancy) { 4490 track1Occupancy = null; 4491 } 4492 } 4493 } 4494 if (crossTrack2 != null) { 4495 block = crossTrack2.getLayoutBlock(); 4496 if (block != null) { 4497 track2Occupancy = block.getOccupancySensor(); 4498 if ((track2Occupancy == crossOccupancy) 4499 || (track2Occupancy == track1Occupancy)) { 4500 track2Occupancy = null; 4501 } 4502 } 4503 } 4504 nextHead = getNextSignalFromObject(track, levelXing, 4505 head.getSystemName(), setSignalsAtXoverTurnoutFrame); 4506 if ((nextHead == null) && (!reachedEndBumper())) { 4507 JmriJOptionPane.showMessageDialog(setSignalsAtLevelXingFrame, 4508 Bundle.getMessage("InfoMessage5", 4509 new Object[]{block.getUserName()}), 4510 Bundle.getMessage("MessageTitle"), 4511 JmriJOptionPane.INFORMATION_MESSAGE); 4512 return; 4513 } 4514 if ((crossOccupancy == null) && (track1Occupancy == null) && (track2Occupancy == null)) { 4515 JmriJOptionPane.showMessageDialog(setSignalsAtLevelXingFrame, 4516 Bundle.getMessage("SignalsWarn1", 4517 new Object[]{signalHeadName}), 4518 Bundle.getMessage("WarningTitle"), 4519 JmriJOptionPane.WARNING_MESSAGE); 4520 } 4521 if (!initializeBlockBossLogic(head.getDisplayName())) { 4522 return; 4523 } 4524 logic.setMode(BlockBossLogic.SINGLEBLOCK); 4525 logic.setSensor1(occupancy.getDisplayName()); 4526 if (nextHead != null) { 4527 logic.setWatchedSignal1(nextHead.getDisplayName(), false); 4528 } 4529 if (auxSignal != null) { 4530 logic.setWatchedSignal1Alt(auxSignal.getDisplayName()); 4531 } 4532 if (crossOccupancy != null) { 4533 logic.setSensor2(crossOccupancy.getDisplayName()); 4534 if (track1Occupancy != null) { 4535 logic.setSensor3(track1Occupancy.getDisplayName()); 4536 if (track2Occupancy != null) { 4537 logic.setSensor4(track2Occupancy.getDisplayName()); 4538 } 4539 } else if (track2Occupancy != null) { 4540 logic.setSensor3(track2Occupancy.getDisplayName()); 4541 } 4542 } else if (track1Occupancy != null) { 4543 logic.setSensor2(track1Occupancy.getDisplayName()); 4544 if (track2Occupancy != null) { 4545 logic.setSensor3(track2Occupancy.getDisplayName()); 4546 } 4547 } else if (track2Occupancy != null) { 4548 logic.setSensor2(track2Occupancy.getDisplayName()); 4549 } 4550 finalizeBlockBossLogic(); 4551 } 4552 4553 /*====================================*\ 4554 |* setSignalsAtThroatToThroatTurnouts *| 4555 \*====================================*/ 4556 /** 4557 * Tool to set signals at throat-to-throat turnouts, including placing the 4558 * signal icons and setup of signal logic for each signal head 4559 * <p> 4560 * This tool can only be accessed from the Tools menu. There is no access 4561 * from a turnout pop-up menu. 4562 * <p> 4563 * This tool requires a situation where two turnouts are connected throat- 4564 * to-throat by a single "short" track segment. The actual length of the 4565 * track segment is not tested. If this situation is not found, and error 4566 * message is sent to the user. To get started with this the user needs to 4567 * enter at least one of the two connected turnouts. 4568 * <p> 4569 * This tool assumes two turnouts connected throat-to-throat, as would be 4570 * used to represent a double slip turnout. The turnouts may be either 4571 * left-handed, right-handed, wye, or any pair of these. This tool also 4572 * assumes that there are no signals at the throat junction. The signal 4573 * heads will be rotated to face outward--away from the throats. Four sets 4574 * of one or two signal heads will be placed, one at each of the converging 4575 * and diverging for each turnout. 4576 * <p> 4577 * This tool assumes that each of the four tracks is contained in a 4578 * different block. Things work best if the two throat-to-throat turnouts 4579 * are in their own separate block, but this is not necessary. 4580 * <p> 4581 * This tool will place icons on the outside edges of each turnout. 4582 * <p> 4583 * At least one signal at each of the four connection points is required. A 4584 * second signal at each is optional. 4585 */ 4586 //operational variables for Set Signals at Double Crossover Turnout tool 4587 private JmriJFrame setSignalsAtThroatToThroatTurnoutsFrame = null; 4588 private boolean setSignalsAtThroatToThroatTurnoutsOpenFlag = false; 4589 private boolean setSignalsAtThroatToThroatTurnoutsFromMenuFlag = false; 4590 4591 private JLabel ttotTurnoutName1Label = null; 4592 private JLabel ttotTurnoutName2Label = null; 4593 4594 private final NamedBeanComboBox<Turnout> turnout1ComboBox = new NamedBeanComboBox<>( 4595 InstanceManager.turnoutManagerInstance(), 4596 null, DisplayOptions.DISPLAYNAME); 4597 private final NamedBeanComboBox<Turnout> turnout2ComboBox = new NamedBeanComboBox<>( 4598 InstanceManager.turnoutManagerInstance(), 4599 null, DisplayOptions.DISPLAYNAME); 4600 4601 private final NamedBeanComboBox<SignalHead> a1TToTSignalHeadComboBox = new NamedBeanComboBox<>( 4602 InstanceManager.getDefault(SignalHeadManager.class 4603 ), 4604 null, DisplayOptions.DISPLAYNAME); 4605 private final NamedBeanComboBox<SignalHead> a2TToTSignalHeadComboBox = new NamedBeanComboBox<>( 4606 InstanceManager.getDefault(SignalHeadManager.class 4607 ), 4608 null, DisplayOptions.DISPLAYNAME); 4609 private final NamedBeanComboBox<SignalHead> b1TToTSignalHeadComboBox = new NamedBeanComboBox<>( 4610 InstanceManager.getDefault(SignalHeadManager.class 4611 ), 4612 null, DisplayOptions.DISPLAYNAME); 4613 private final NamedBeanComboBox<SignalHead> b2TToTSignalHeadComboBox = new NamedBeanComboBox<>( 4614 InstanceManager.getDefault(SignalHeadManager.class 4615 ), 4616 null, DisplayOptions.DISPLAYNAME); 4617 private final NamedBeanComboBox<SignalHead> c1TToTSignalHeadComboBox = new NamedBeanComboBox<>( 4618 InstanceManager.getDefault(SignalHeadManager.class 4619 ), 4620 null, DisplayOptions.DISPLAYNAME); 4621 private final NamedBeanComboBox<SignalHead> c2TToTSignalHeadComboBox = new NamedBeanComboBox<>( 4622 InstanceManager.getDefault(SignalHeadManager.class 4623 ), 4624 null, DisplayOptions.DISPLAYNAME); 4625 private final NamedBeanComboBox<SignalHead> d1TToTSignalHeadComboBox = new NamedBeanComboBox<>( 4626 InstanceManager.getDefault(SignalHeadManager.class 4627 ), 4628 null, DisplayOptions.DISPLAYNAME); 4629 private final NamedBeanComboBox<SignalHead> d2TToTSignalHeadComboBox = new NamedBeanComboBox<>( 4630 InstanceManager.getDefault(SignalHeadManager.class 4631 ), 4632 null, DisplayOptions.DISPLAYNAME); 4633 4634 private final JCheckBox setA1TToTHead = new JCheckBox(Bundle.getMessage("PlaceHead")); 4635 private final JCheckBox setA2TToTHead = new JCheckBox(Bundle.getMessage("PlaceHead")); 4636 private final JCheckBox setB1TToTHead = new JCheckBox(Bundle.getMessage("PlaceHead")); 4637 private final JCheckBox setB2TToTHead = new JCheckBox(Bundle.getMessage("PlaceHead")); 4638 private final JCheckBox setC1TToTHead = new JCheckBox(Bundle.getMessage("PlaceHead")); 4639 private final JCheckBox setC2TToTHead = new JCheckBox(Bundle.getMessage("PlaceHead")); 4640 private final JCheckBox setD1TToTHead = new JCheckBox(Bundle.getMessage("PlaceHead")); 4641 private final JCheckBox setD2TToTHead = new JCheckBox(Bundle.getMessage("PlaceHead")); 4642 4643 private final JCheckBox setupA1TToTLogic = new JCheckBox(Bundle.getMessage("SetLogic")); 4644 private final JCheckBox setupA2TToTLogic = new JCheckBox(Bundle.getMessage("SetLogic")); 4645 private final JCheckBox setupB1TToTLogic = new JCheckBox(Bundle.getMessage("SetLogic")); 4646 private final JCheckBox setupB2TToTLogic = new JCheckBox(Bundle.getMessage("SetLogic")); 4647 private final JCheckBox setupC1TToTLogic = new JCheckBox(Bundle.getMessage("SetLogic")); 4648 private final JCheckBox setupC2TToTLogic = new JCheckBox(Bundle.getMessage("SetLogic")); 4649 private final JCheckBox setupD1TToTLogic = new JCheckBox(Bundle.getMessage("SetLogic")); 4650 private final JCheckBox setupD2TToTLogic = new JCheckBox(Bundle.getMessage("SetLogic")); 4651 4652 private JButton getSavedTToTSignalHeads = null; 4653 private JButton changeTToTSignalIcon = null; 4654 private JButton setTToTSignalsDone = null; 4655 private JButton setTToTSignalsCancel = null; 4656 4657 private LayoutTurnout layoutTurnout1 = null; 4658 private LayoutTurnout layoutTurnout2 = null; 4659 4660 private Turnout turnout1 = null; 4661 private Turnout turnout2 = null; 4662 4663 private TrackSegment connectorTrack = null; 4664 4665 private String ttotTurnoutName1 = null; 4666 private String ttotTurnoutName2 = null; 4667 4668 private SignalHead a1TToTHead = null; 4669 private SignalHead a2TToTHead = null; 4670 private SignalHead b1TToTHead = null; 4671 private SignalHead b2TToTHead = null; 4672 private SignalHead c1TToTHead = null; 4673 private SignalHead c2TToTHead = null; 4674 private SignalHead d1TToTHead = null; 4675 private SignalHead d2TToTHead = null; 4676 4677 public void setSignalsAtThroatToThroatTurnoutsFromMenu( 4678 @Nonnull LayoutTurnout to, @Nonnull String linkedTurnoutName, 4679 @Nonnull MultiIconEditor theEditor, @Nonnull JFrame theFrame) { 4680 ttotTurnoutName1 = to.getTurnoutName(); 4681 ttotTurnoutName2 = linkedTurnoutName; 4682 4683 turnout1ComboBox.setSelectedItem(to.getTurnout()); 4684 turnout2ComboBox.setSelectedItem(to.getSecondTurnout()); 4685 4686 a1TToTSignalHeadComboBox.setSelectedItem(null); 4687 a2TToTSignalHeadComboBox.setSelectedItem(null); 4688 b1TToTSignalHeadComboBox.setSelectedItem(null); 4689 b2TToTSignalHeadComboBox.setSelectedItem(null); 4690 c1TToTSignalHeadComboBox.setSelectedItem(null); 4691 c2TToTSignalHeadComboBox.setSelectedItem(null); 4692 d1TToTSignalHeadComboBox.setSelectedItem(null); 4693 d2TToTSignalHeadComboBox.setSelectedItem(null); 4694 4695 setSignalsAtThroatToThroatTurnoutsFromMenuFlag = true; 4696 setSignalsAtThroatToThroatTurnouts(theEditor, theFrame); 4697 setSignalsAtThroatToThroatTurnoutsFromMenuFlag = false; 4698 } 4699 4700 public void setSignalsAtThroatToThroatTurnouts( 4701 @Nonnull MultiIconEditor theEditor, @Nonnull JFrame theFrame) { 4702 signalIconEditor = theEditor; 4703 signalFrame = theFrame; 4704 4705 //Initialize if needed 4706 if (setSignalsAtThroatToThroatTurnoutsFrame == null) { 4707 setSignalsAtThroatToThroatTurnoutsOpenFlag = false; 4708 setSignalsAtThroatToThroatTurnoutsFrame = new JmriJFrame(Bundle.getMessage("SignalsAtTToTTurnout"), false, true); 4709 oneFrameToRuleThemAll(setSignalsAtThroatToThroatTurnoutsFrame); 4710 setSignalsAtThroatToThroatTurnoutsFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 4711 setSignalsAtThroatToThroatTurnoutsFrame.addHelpMenu("package.jmri.jmrit.display.SetSignalsAtTToTTurnout", true); 4712 setSignalsAtThroatToThroatTurnoutsFrame.setLocation(70, 30); 4713 Container theContentPane = setSignalsAtThroatToThroatTurnoutsFrame.getContentPane(); 4714 theContentPane.setLayout(new BoxLayout(theContentPane, BoxLayout.Y_AXIS)); 4715 4716 JPanel panel1a = new JPanel(new FlowLayout()); 4717 ttotTurnoutName1Label = new JLabel(Bundle.getMessage("BeanNameTurnout") + " 1 " 4718 + Bundle.getMessage("Name")); 4719 panel1a.add(ttotTurnoutName1Label); 4720 panel1a.add(turnout1ComboBox); 4721 turnout1ComboBox.setToolTipText(Bundle.getMessage("SignalsTurnoutNameHint")); 4722 theContentPane.add(panel1a); 4723 4724 JPanel panel1b = new JPanel(new FlowLayout()); 4725 ttotTurnoutName2Label = new JLabel(Bundle.getMessage("BeanNameTurnout") + " 2 " 4726 + Bundle.getMessage("Name")); 4727 panel1b.add(ttotTurnoutName2Label); 4728 panel1b.add(turnout2ComboBox); 4729 turnout2ComboBox.setToolTipText(Bundle.getMessage("SignalsTurnoutNameHint")); 4730 theContentPane.add(panel1b); 4731 theContentPane.add(new JSeparator(JSeparator.HORIZONTAL)); 4732 //Provide for retrieval of names of previously saved signal heads 4733 4734 JPanel panel20 = new JPanel(new FlowLayout()); 4735 JLabel shTitle = new JLabel(Bundle.getMessage("SignalHeads")); 4736 panel20.add(shTitle); 4737 panel20.add(new JLabel(" ")); 4738 panel20.add(getSavedTToTSignalHeads = new JButton(Bundle.getMessage("GetSaved"))); 4739 getSavedTToTSignalHeads.addActionListener(this::setSignalsAtTToTTurnoutsGetSaved); 4740 getSavedTToTSignalHeads.setToolTipText(Bundle.getMessage("GetSavedHint")); 4741 theContentPane.add(panel20); 4742 theContentPane.add(new JSeparator(JSeparator.HORIZONTAL)); 4743 4744 JPanel panel2a = new JPanel(new FlowLayout()); 4745 panel2a.add(new JLabel(" ")); 4746 panel2a.add(setPlaceAllHeads); 4747 setPlaceAllHeads.setToolTipText(Bundle.getMessage("PlaceAllHeadsHint")); 4748 setPlaceAllHeads.addActionListener((ActionEvent e) -> { 4749 boolean isSelected = setPlaceAllHeads.isSelected(); 4750 //(de)select all checkboxes 4751 setA1TToTHead.setSelected(isSelected); 4752 setA2TToTHead.setSelected(isSelected); 4753 setB1TToTHead.setSelected(isSelected); 4754 setB2TToTHead.setSelected(isSelected); 4755 setC1TToTHead.setSelected(isSelected); 4756 setC2TToTHead.setSelected(isSelected); 4757 setD1TToTHead.setSelected(isSelected); 4758 setD2TToTHead.setSelected(isSelected); 4759 }); 4760 panel2a.add(new JLabel(" ")); 4761 panel2a.add(setupAllLogic); 4762 setupAllLogic.setToolTipText(Bundle.getMessage("SetAllLogicHint")); 4763 setupAllLogic.addActionListener((ActionEvent e) -> { 4764 boolean isSelected = setupAllLogic.isSelected(); 4765 //(de)select all checkboxes 4766 setupA1TToTLogic.setSelected(isSelected); 4767 setupA2TToTLogic.setSelected(isSelected); 4768 setupB1TToTLogic.setSelected(isSelected); 4769 setupB2TToTLogic.setSelected(isSelected); 4770 setupC1TToTLogic.setSelected(isSelected); 4771 setupC2TToTLogic.setSelected(isSelected); 4772 setupD1TToTLogic.setSelected(isSelected); 4773 setupD2TToTLogic.setSelected(isSelected); 4774 }); 4775 theContentPane.add(panel2a); 4776 theContentPane.add(new JSeparator(JSeparator.HORIZONTAL)); 4777 4778 //Signal heads located at turnout 1 4779 JPanel panel20a = new JPanel(new FlowLayout()); 4780 panel20a.add(new JLabel(Bundle.getMessage("SignalLocated") 4781 + " " + Bundle.getMessage("BeanNameTurnout") + " 1 - " 4782 + Bundle.getMessage("ContinuingTrack"))); 4783 theContentPane.add(panel20a); 4784 4785 JPanel panel21 = new JPanel(new FlowLayout()); 4786 panel21.add(new JLabel(Bundle.getMessage("MakeLabel", 4787 Bundle.getMessage("ProtectsTurnout") + " 2 - " 4788 + Bundle.getMessage("ContinuingTrack")))); 4789 panel21.add(a1TToTSignalHeadComboBox); 4790 theContentPane.add(panel21); 4791 a1TToTSignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 4792 4793 JPanel panel22 = new JPanel(new FlowLayout()); 4794 panel22.add(new JLabel(Bundle.getMessage("OrBoth") + " 2 " + Bundle.getMessage("Tracks)") + " ")); 4795 panel22.add(setA1TToTHead); 4796 setA1TToTHead.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 4797 panel22.add(new JLabel(" ")); 4798 panel22.add(setupA1TToTLogic); 4799 setupA1TToTLogic.setToolTipText(Bundle.getMessage("SetLogicHint")); 4800 theContentPane.add(panel22); 4801 4802 JPanel panel23 = new JPanel(new FlowLayout()); 4803 panel23.add(new JLabel(Bundle.getMessage("MakeLabel", 4804 Bundle.getMessage("ProtectsTurnout") + " 2 - " 4805 + Bundle.getMessage("DivergingTrack")))); 4806 panel23.add(a2TToTSignalHeadComboBox); 4807 theContentPane.add(panel23); 4808 a2TToTSignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 4809 4810 JPanel panel24 = new JPanel(new FlowLayout()); 4811 panel24.add(new JLabel(" ")); 4812 panel24.add(setA2TToTHead); 4813 setA2TToTHead.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 4814 panel24.add(new JLabel(" ")); 4815 panel24.add(setupA2TToTLogic); 4816 setupA2TToTLogic.setToolTipText(Bundle.getMessage("SetLogicHint")); 4817 theContentPane.add(panel24); 4818 4819 JPanel panel31x = new JPanel(new FlowLayout()); 4820 panel31x.add(new JLabel(Bundle.getMessage("SignalLocated") 4821 + " " + Bundle.getMessage("BeanNameTurnout") + " 1 - " 4822 + Bundle.getMessage("DivergingTrack"))); 4823 theContentPane.add(panel31x); 4824 4825 JPanel panel31 = new JPanel(new FlowLayout()); 4826 panel31.add(new JLabel(Bundle.getMessage("MakeLabel", 4827 Bundle.getMessage("ProtectsTurnout") + " 2 - " 4828 + Bundle.getMessage("ContinuingTrack")))); 4829 panel31.add(b1TToTSignalHeadComboBox); 4830 theContentPane.add(panel31); 4831 b1TToTSignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 4832 4833 JPanel panel32 = new JPanel(new FlowLayout()); 4834 panel32.add(new JLabel(Bundle.getMessage("OrBoth") + " 2 " + Bundle.getMessage("Tracks)") + " ")); 4835 panel32.add(setB1TToTHead); 4836 setB1TToTHead.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 4837 panel32.add(new JLabel(" ")); 4838 panel32.add(setupB1TToTLogic); 4839 setupB1TToTLogic.setToolTipText(Bundle.getMessage("SetLogicHint")); 4840 theContentPane.add(panel32); 4841 4842 JPanel panel33 = new JPanel(new FlowLayout()); 4843 panel33.add(new JLabel(Bundle.getMessage("MakeLabel", 4844 Bundle.getMessage("ProtectsTurnout") + " 2 - " 4845 + Bundle.getMessage("DivergingTrack")))); 4846 panel33.add(b2TToTSignalHeadComboBox); 4847 theContentPane.add(panel33); 4848 b2TToTSignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 4849 4850 JPanel panel34 = new JPanel(new FlowLayout()); 4851 panel34.add(new JLabel(" ")); 4852 panel34.add(setB2TToTHead); 4853 setB2TToTHead.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 4854 panel34.add(new JLabel(" ")); 4855 panel34.add(setupB2TToTLogic); 4856 setupB2TToTLogic.setToolTipText(Bundle.getMessage("SetLogicHint")); 4857 theContentPane.add(panel34); 4858 theContentPane.add(new JSeparator(JSeparator.HORIZONTAL)); 4859 //Signal heads located at turnout 2 4860 4861 JPanel panel41x = new JPanel(new FlowLayout()); 4862 panel41x.add(new JLabel(Bundle.getMessage("SignalLocated") 4863 + " " + Bundle.getMessage("BeanNameTurnout") + " 2 - " 4864 + Bundle.getMessage("ContinuingTrack"))); 4865 theContentPane.add(panel41x); 4866 4867 JPanel panel41 = new JPanel(new FlowLayout()); 4868 panel33.add(new JLabel(Bundle.getMessage("MakeLabel", 4869 Bundle.getMessage("ProtectsTurnout") + " 1 - " 4870 + Bundle.getMessage("ContinuingTrack")))); 4871 panel41.add(c1TToTSignalHeadComboBox); 4872 theContentPane.add(panel41); 4873 c1TToTSignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 4874 4875 JPanel panel42 = new JPanel(new FlowLayout()); 4876 panel42.add(new JLabel(Bundle.getMessage("OrBoth") + " 1 " + Bundle.getMessage("Tracks)") + " ")); 4877 panel42.add(setC1TToTHead); 4878 setC1TToTHead.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 4879 panel42.add(new JLabel(" ")); 4880 panel42.add(setupC1TToTLogic); 4881 setupC1TToTLogic.setToolTipText(Bundle.getMessage("SetLogicHint")); 4882 theContentPane.add(panel42); 4883 4884 JPanel panel43 = new JPanel(new FlowLayout()); 4885 panel43.add(new JLabel(Bundle.getMessage("MakeLabel", 4886 Bundle.getMessage("ProtectsTurnout") + " 1 - " 4887 + Bundle.getMessage("DivergingTrack")))); 4888 panel43.add(c2TToTSignalHeadComboBox); 4889 theContentPane.add(panel43); 4890 c2TToTSignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 4891 4892 JPanel panel44 = new JPanel(new FlowLayout()); 4893 panel44.add(new JLabel(" ")); 4894 panel44.add(setC2TToTHead); 4895 setC2TToTHead.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 4896 panel44.add(new JLabel(" ")); 4897 panel44.add(setupC2TToTLogic); 4898 setupC2TToTLogic.setToolTipText(Bundle.getMessage("SetLogicHint")); 4899 theContentPane.add(panel44); 4900 4901 JPanel panel51x = new JPanel(new FlowLayout()); 4902 panel51x.add(new JLabel(Bundle.getMessage("SignalLocated") 4903 + " " + Bundle.getMessage("BeanNameTurnout") + " 2 - " 4904 + Bundle.getMessage("DivergingTrack"))); 4905 theContentPane.add(panel51x); 4906 4907 JPanel panel51 = new JPanel(new FlowLayout()); 4908 panel51.add(new JLabel(Bundle.getMessage("MakeLabel", 4909 Bundle.getMessage("ProtectsTurnout") + " 1 - " 4910 + Bundle.getMessage("ContinuingTrack")))); 4911 panel51.add(d1TToTSignalHeadComboBox); 4912 theContentPane.add(panel51); 4913 d1TToTSignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 4914 4915 JPanel panel52 = new JPanel(new FlowLayout()); 4916 panel52.add(new JLabel(Bundle.getMessage("OrBoth") + " 1 " + Bundle.getMessage("Tracks)") + " ")); 4917 panel52.add(setD1TToTHead); 4918 setD1TToTHead.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 4919 panel52.add(new JLabel(" ")); 4920 panel52.add(setupD1TToTLogic); 4921 setupD1TToTLogic.setToolTipText(Bundle.getMessage("SetLogicHint")); 4922 theContentPane.add(panel52); 4923 4924 JPanel panel53 = new JPanel(new FlowLayout()); 4925 panel53.add(new JLabel(Bundle.getMessage("MakeLabel", 4926 Bundle.getMessage("ProtectsTurnout") + " 1 - " 4927 + Bundle.getMessage("DivergingTrack")))); 4928 panel53.add(d2TToTSignalHeadComboBox); 4929 theContentPane.add(panel53); 4930 d2TToTSignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 4931 4932 JPanel panel54 = new JPanel(new FlowLayout()); 4933 panel54.add(new JLabel(" ")); 4934 panel54.add(setD2TToTHead); 4935 setD2TToTHead.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 4936 panel54.add(new JLabel(" ")); 4937 panel54.add(setupD2TToTLogic); 4938 setupD2TToTLogic.setToolTipText(Bundle.getMessage("SetLogicHint")); 4939 theContentPane.add(panel54); 4940 theContentPane.add(new JSeparator(JSeparator.HORIZONTAL)); 4941 4942 JPanel panel6 = new JPanel(new FlowLayout()); 4943 panel6.add(changeTToTSignalIcon = new JButton(Bundle.getMessage("ChangeSignalIcon"))); 4944 changeTToTSignalIcon.addActionListener((ActionEvent e) -> signalFrame.setVisible(true)); 4945 changeTToTSignalIcon.setToolTipText(Bundle.getMessage("ChangeSignalIconHint")); 4946 panel6.add(new JLabel(" ")); 4947 panel6.add(setTToTSignalsDone = new JButton(Bundle.getMessage("ButtonDone"))); 4948 setTToTSignalsDone.addActionListener(this::setTToTSignalsDonePressed); 4949 setTToTSignalsDone.setToolTipText(Bundle.getMessage("DoneHint", Bundle.getMessage("ButtonDone"))); 4950 4951 panel6.add(setTToTSignalsCancel = new JButton(Bundle.getMessage("ButtonCancel"))); 4952 setTToTSignalsCancel.addActionListener(this::setTToTSignalsCancelPressed); 4953 setTToTSignalsCancel.setToolTipText(Bundle.getMessage("CancelHint", Bundle.getMessage("ButtonCancel"))); 4954 theContentPane.add(panel6); 4955 4956 //make this button the default button (return or enter activates) 4957 JRootPane rootPane = SwingUtilities.getRootPane(setTToTSignalsDone); 4958 if (rootPane != null) { 4959 rootPane.setDefaultButton(setTToTSignalsDone); 4960 } 4961 4962 setSignalsAtThroatToThroatTurnoutsFrame.addWindowListener(new WindowAdapter() { 4963 @Override 4964 public void windowClosing(WindowEvent e) { 4965 setTToTSignalsCancelPressed(null); 4966 } 4967 }); 4968 } 4969 setPlaceAllHeads.setSelected(false); 4970 setupAllLogic.setSelected(false); 4971 4972 turnout1ComboBox.setVisible(!setSignalsAtThroatToThroatTurnoutsFromMenuFlag); 4973 turnout2ComboBox.setVisible(!setSignalsAtThroatToThroatTurnoutsFromMenuFlag); 4974 4975 if (setSignalsAtThroatToThroatTurnoutsFromMenuFlag) { 4976 ttotTurnoutName1Label.setText(Bundle.getMessage("MakeLabel", 4977 Bundle.getMessage("BeanNameTurnout") + " 1 " 4978 + Bundle.getMessage("Name")) + ttotTurnoutName1); 4979 ttotTurnoutName2Label.setText(Bundle.getMessage("MakeLabel", 4980 Bundle.getMessage("BeanNameTurnout") + " 2 " 4981 + Bundle.getMessage("Name")) + ttotTurnoutName2); 4982 4983 SwingUtilities.invokeLater(() -> setSignalsAtTToTTurnoutsGetSaved(null)); 4984 } else { 4985 ttotTurnoutName1Label.setText( 4986 Bundle.getMessage("BeanNameTurnout") + " 1 " 4987 + Bundle.getMessage("Name")); 4988 ttotTurnoutName2Label.setText( 4989 Bundle.getMessage("BeanNameTurnout") + " 2 " 4990 + Bundle.getMessage("Name")); 4991 } 4992 4993 if (!setSignalsAtThroatToThroatTurnoutsOpenFlag) { 4994 setSignalsAtThroatToThroatTurnoutsFrame.setPreferredSize(null); 4995 setSignalsAtThroatToThroatTurnoutsFrame.pack(); 4996 setSignalsAtThroatToThroatTurnoutsOpenFlag = true; 4997 } 4998 setSignalsAtThroatToThroatTurnoutsFrame.setVisible(true); 4999 } //setSignalsAtTToTTurnouts 5000 5001 private void setSignalsAtTToTTurnoutsGetSaved(ActionEvent a) { 5002 if (!getTToTTurnoutInformation()) { 5003 return; 5004 } 5005 a1TToTSignalHeadComboBox.setSelectedItem(layoutTurnout1.getSignalB1()); 5006 a2TToTSignalHeadComboBox.setSelectedItem(layoutTurnout1.getSignalB2()); 5007 b1TToTSignalHeadComboBox.setSelectedItem(layoutTurnout1.getSignalC1()); 5008 b2TToTSignalHeadComboBox.setSelectedItem(layoutTurnout1.getSignalC2()); 5009 c1TToTSignalHeadComboBox.setSelectedItem(layoutTurnout2.getSignalB1()); 5010 c2TToTSignalHeadComboBox.setSelectedItem(layoutTurnout2.getSignalB2()); 5011 d1TToTSignalHeadComboBox.setSelectedItem(layoutTurnout2.getSignalC1()); 5012 d2TToTSignalHeadComboBox.setSelectedItem(layoutTurnout2.getSignalC2()); 5013 } 5014 5015 private void setTToTSignalsCancelPressed(ActionEvent a) { 5016 setSignalsAtThroatToThroatTurnoutsOpenFlag = false; 5017 setSignalsAtThroatToThroatTurnoutsFrame.setVisible(false); 5018 } 5019 5020 private boolean getTToTTurnoutInformation() { 5021 HitPointType type = HitPointType.NONE; 5022 Object connect = null; 5023 5024 turnout1 = null; 5025 turnout2 = null; 5026 5027 layoutTurnout1 = null; 5028 layoutTurnout2 = null; 5029 5030 if (!setSignalsAtThroatToThroatTurnoutsFromMenuFlag) { 5031 ttotTurnoutName1 = turnout1ComboBox.getSelectedItemDisplayName(); 5032 if (ttotTurnoutName1 == null) { 5033 ttotTurnoutName1 = ""; 5034 } 5035 } 5036 if (ttotTurnoutName1.isEmpty()) { 5037 //turnout 1 not entered, test turnout 2 5038 ttotTurnoutName2 = turnout2ComboBox.getSelectedItemDisplayName(); 5039 if (ttotTurnoutName2 == null) { 5040 ttotTurnoutName2 = ""; 5041 } 5042 if (ttotTurnoutName2.isEmpty()) { 5043 //no entries in turnout fields 5044 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5045 Bundle.getMessage("SignalsError1"), 5046 Bundle.getMessage("ErrorTitle"), 5047 JmriJOptionPane.ERROR_MESSAGE); 5048 return false; 5049 } 5050 turnout2 = InstanceManager.turnoutManagerInstance().getTurnout(ttotTurnoutName2); 5051 if (turnout2 == null) { 5052 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5053 Bundle.getMessage("SignalsError2", 5054 new Object[]{ttotTurnoutName2}), Bundle.getMessage("ErrorTitle"), 5055 JmriJOptionPane.ERROR_MESSAGE); 5056 return false; 5057 } 5058 String uname = turnout2.getUserName(); 5059 if ((uname == null) || uname.isEmpty() 5060 || !uname.equals(ttotTurnoutName2)) { 5061 turnout2ComboBox.setSelectedItem(turnout2); 5062 } 5063 layoutTurnout2 = getLayoutTurnoutFromTurnout(turnout2, false, ttotTurnoutName2, setSignalsAtThroatToThroatTurnoutsFrame); 5064 if (layoutTurnout2 == null) { 5065 return false; 5066 } 5067 //have turnout 2 and layout turnout 2 - look for turnout 1 5068 connectorTrack = (TrackSegment) layoutTurnout2.getConnectA(); 5069 if (connectorTrack == null) { 5070 //Inform user of error, and terminate 5071 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5072 Bundle.getMessage("SignalsError18"), 5073 Bundle.getMessage("ErrorTitle"), 5074 JmriJOptionPane.ERROR_MESSAGE); 5075 return false; 5076 } 5077 type = connectorTrack.getType1(); 5078 connect = connectorTrack.getConnect1(); 5079 if (connect == layoutTurnout2) { 5080 type = connectorTrack.getType2(); 5081 connect = connectorTrack.getConnect2(); 5082 } 5083 if ((type != HitPointType.TURNOUT_A) || (connect == null)) { 5084 //Not two turnouts connected throat-to-throat by a single Track Segment 5085 //Inform user of error and terminate 5086 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5087 Bundle.getMessage("SignalsError18"), 5088 Bundle.getMessage("ErrorTitle"), 5089 JmriJOptionPane.ERROR_MESSAGE); 5090 return false; 5091 } 5092 layoutTurnout1 = (LayoutTurnout) connect; 5093 turnout1 = layoutTurnout1.getTurnout(); 5094 if (turnout1 == null) { 5095 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5096 Bundle.getMessage("SignalsError18"), 5097 Bundle.getMessage("ErrorTitle"), 5098 JmriJOptionPane.ERROR_MESSAGE); 5099 return false; 5100 } 5101 turnout1ComboBox.setSelectedItem(turnout1); 5102 } else { 5103 //something was entered in the turnout 1 field 5104 turnout1 = InstanceManager.turnoutManagerInstance().getTurnout(ttotTurnoutName1); 5105 if (turnout1 == null) { 5106 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5107 Bundle.getMessage("SignalsError2", 5108 new Object[]{ttotTurnoutName1}), Bundle.getMessage("ErrorTitle"), 5109 JmriJOptionPane.ERROR_MESSAGE); 5110 return false; 5111 } 5112 String uname = turnout1.getUserName(); 5113 if ((uname == null) || uname.isEmpty() || !uname.equals(ttotTurnoutName1)) { 5114 turnout1ComboBox.setSelectedItem(turnout1); 5115 } 5116 //have turnout 1 - get corresponding layoutTurnout 5117 layoutTurnout1 = getLayoutTurnoutFromTurnout(turnout1, false, ttotTurnoutName1, setSignalsAtThroatToThroatTurnoutsFrame); 5118 if (layoutTurnout1 == null) { 5119 return false; 5120 } 5121 turnout1ComboBox.setSelectedItem(layoutTurnout1.getTurnout()); 5122 //have turnout 1 and layout turnout 1 - was something entered for turnout 2 5123 ttotTurnoutName2 = turnout2ComboBox.getSelectedItemDisplayName(); 5124 if (ttotTurnoutName2 == null) { 5125 ttotTurnoutName2 = ""; 5126 } 5127 if (ttotTurnoutName2.isEmpty()) { 5128 //no entry for turnout 2 5129 connectorTrack = (TrackSegment) layoutTurnout1.getConnectA(); 5130 if (connectorTrack == null) { 5131 //Inform user of error, and terminate 5132 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5133 Bundle.getMessage("SignalsError18"), 5134 Bundle.getMessage("ErrorTitle"), 5135 JmriJOptionPane.ERROR_MESSAGE); 5136 return false; 5137 } 5138 type = connectorTrack.getType1(); 5139 connect = connectorTrack.getConnect1(); 5140 if (connect == layoutTurnout1) { 5141 type = connectorTrack.getType2(); 5142 connect = connectorTrack.getConnect2(); 5143 } 5144 if ((type != HitPointType.TURNOUT_A) || (connect == null)) { 5145 //Not two turnouts connected throat-to-throat by a single Track Segment 5146 //Inform user of error and terminate 5147 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5148 Bundle.getMessage("SignalsError18"), 5149 Bundle.getMessage("ErrorTitle"), 5150 JmriJOptionPane.ERROR_MESSAGE); 5151 return false; 5152 } 5153 layoutTurnout2 = (LayoutTurnout) connect; 5154 turnout2 = layoutTurnout2.getTurnout(); 5155 if (turnout2 == null) { 5156 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5157 Bundle.getMessage("SignalsError18"), 5158 Bundle.getMessage("ErrorTitle"), 5159 JmriJOptionPane.ERROR_MESSAGE); 5160 return false; 5161 } 5162 turnout2ComboBox.setSelectedItem(turnout2); 5163 } else { 5164 //turnout 2 entered also 5165 turnout2 = InstanceManager.turnoutManagerInstance().getTurnout(ttotTurnoutName2); 5166 if (turnout2 == null) { 5167 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5168 Bundle.getMessage("SignalsError2", 5169 new Object[]{ttotTurnoutName2}), Bundle.getMessage("ErrorTitle"), 5170 JmriJOptionPane.ERROR_MESSAGE); 5171 return false; 5172 } 5173 uname = turnout2.getUserName(); 5174 if ((uname == null) || uname.isEmpty() || !uname.equals(ttotTurnoutName2)) { 5175 turnout2ComboBox.setSelectedItem(turnout2); 5176 } 5177 layoutTurnout2 = getLayoutTurnoutFromTurnout(turnout2, false, ttotTurnoutName2, setSignalsAtThroatToThroatTurnoutsFrame); 5178 if (layoutTurnout2 == null) { 5179 return false; 5180 } 5181 turnout2ComboBox.setSelectedItem(layoutTurnout2.getTurnout()); 5182 //check that layout turnout 1 and layout turnout 2 are connected throat-to-throat 5183 if (layoutTurnout1.getConnectA() != layoutTurnout2.getConnectA()) { 5184 //Not two turnouts connected throat-to-throat by a single Track Segment 5185 //Inform user of error and terminate 5186 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5187 Bundle.getMessage("SignalsError18"), 5188 Bundle.getMessage("ErrorTitle"), 5189 JmriJOptionPane.ERROR_MESSAGE); 5190 return false; 5191 } 5192 connectorTrack = (TrackSegment) layoutTurnout1.getConnectA(); 5193 } 5194 } 5195 //have both turnouts, correctly connected - complete initialization 5196 LayoutTurnoutView layoutTurnout1View = layoutEditor.getLayoutTurnoutView(layoutTurnout1); 5197 Point2D coordsA = layoutTurnout1View.getCoordsA(); 5198 Point2D coordsCenter = layoutTurnout1View.getCoordsCenter(); 5199 placeSignalDirectionDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsCenter, coordsA)); 5200 return true; 5201 } //getTToTTurnoutInformation 5202 5203 private void setTToTSignalsDonePressed(ActionEvent a) { 5204 if (!getTToTTurnoutInformation()) { 5205 return; 5206 } 5207 if (!getTToTSignalHeadInformation()) { 5208 return; 5209 } 5210 5211 //place signal icons if requested, and assign signal heads to this turnout 5212 String signalHeadName = a1TToTSignalHeadComboBox.getSelectedItemDisplayName(); 5213 if (signalHeadName == null) { 5214 signalHeadName = ""; 5215 } 5216 if (setA1TToTHead.isSelected()) { 5217 if (isHeadOnPanel(a1TToTHead) 5218 && (a1TToTHead != getHeadFromName(layoutTurnout1.getSignalB1Name()))) { 5219 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5220 Bundle.getMessage("SignalsError6", 5221 new Object[]{signalHeadName}), 5222 Bundle.getMessage("ErrorTitle"), 5223 JmriJOptionPane.ERROR_MESSAGE); 5224 return; 5225 } else { 5226 removeSignalHeadFromPanel(layoutTurnout1.getSignalB1Name()); 5227 if (layoutTurnout1.getContinuingSense() == Turnout.CLOSED) { 5228 placeA1TToT(signalHeadName); 5229 } else { 5230 placeB1TToT(signalHeadName); 5231 } 5232 removeAssignment(a1TToTHead); 5233 layoutTurnout1.setSignalB1Name(signalHeadName); 5234 needRedraw = true; 5235 } 5236 } else { 5237 LayoutTurnout.Geometry assigned = isHeadAssignedHere(a1TToTHead, layoutTurnout1); 5238 if (assigned == LayoutTurnout.Geometry.NONE) { 5239 if (isHeadOnPanel(a1TToTHead) 5240 && isHeadAssignedAnywhere(a1TToTHead)) { 5241 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5242 Bundle.getMessage("SignalsError8", 5243 new Object[]{signalHeadName}), 5244 Bundle.getMessage("ErrorTitle"), 5245 JmriJOptionPane.ERROR_MESSAGE); 5246 return; 5247 } else { 5248 removeSignalHeadFromPanel(layoutTurnout1.getSignalB1Name()); 5249 removeAssignment(a1TToTHead); 5250 layoutTurnout1.setSignalB1Name(signalHeadName); 5251 } 5252 //} else if (assigned != B1) { 5253 //need to figure out what to do in this case - assigned to a different position on the same turnout. 5254 } 5255 } 5256 5257 signalHeadName = a2TToTSignalHeadComboBox.getSelectedItemDisplayName(); 5258 if (signalHeadName == null) { 5259 signalHeadName = ""; 5260 } 5261 if ((a2TToTHead != null) && setA2TToTHead.isSelected()) { 5262 if (isHeadOnPanel(a2TToTHead) 5263 && (a2TToTHead != getHeadFromName(layoutTurnout1.getSignalB2Name()))) { 5264 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5265 Bundle.getMessage("SignalsError6", 5266 new Object[]{signalHeadName}), 5267 Bundle.getMessage("ErrorTitle"), 5268 JmriJOptionPane.ERROR_MESSAGE); 5269 return; 5270 } else { 5271 removeSignalHeadFromPanel(layoutTurnout1.getSignalB2Name()); 5272 if (layoutTurnout1.getContinuingSense() == Turnout.CLOSED) { 5273 placeA2TToT(signalHeadName); 5274 } else { 5275 placeB2TToT(signalHeadName); 5276 } 5277 removeAssignment(a2TToTHead); 5278 layoutTurnout1.setSignalB2Name(signalHeadName); 5279 needRedraw = true; 5280 } 5281 } else if (a2TToTHead != null) { 5282 LayoutTurnout.Geometry assigned = isHeadAssignedHere(a2TToTHead, layoutTurnout1); 5283 if (assigned == LayoutTurnout.Geometry.NONE) { 5284 if (isHeadOnPanel(a2TToTHead) 5285 && isHeadAssignedAnywhere(a2TToTHead)) { 5286 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5287 Bundle.getMessage("SignalsError8", 5288 new Object[]{signalHeadName}), 5289 Bundle.getMessage("ErrorTitle"), 5290 JmriJOptionPane.ERROR_MESSAGE); 5291 return; 5292 } else { 5293 removeSignalHeadFromPanel(layoutTurnout1.getSignalB2Name()); 5294 removeAssignment(a2TToTHead); 5295 layoutTurnout1.setSignalB2Name(signalHeadName); 5296 } 5297 //} else if (assigned != B2) { 5298 //need to figure out what to do in this case. 5299 } 5300 } else { //a2TToTHead known to be null here 5301 removeSignalHeadFromPanel(layoutTurnout1.getSignalB2Name()); 5302 layoutTurnout1.setSignalB2Name(""); 5303 } 5304 5305 signalHeadName = b1TToTSignalHeadComboBox.getSelectedItemDisplayName(); 5306 if (signalHeadName == null) { 5307 signalHeadName = ""; 5308 } 5309 if (setB1TToTHead.isSelected()) { 5310 if (isHeadOnPanel(b1TToTHead) 5311 && (b1TToTHead != getHeadFromName(layoutTurnout1.getSignalC1Name()))) { 5312 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5313 Bundle.getMessage("SignalsError6", 5314 new Object[]{signalHeadName}), 5315 Bundle.getMessage("ErrorTitle"), 5316 JmriJOptionPane.ERROR_MESSAGE); 5317 return; 5318 } else { 5319 removeSignalHeadFromPanel(layoutTurnout1.getSignalC1Name()); 5320 if (layoutTurnout1.getContinuingSense() == Turnout.CLOSED) { 5321 placeB1TToT(signalHeadName); 5322 } else { 5323 placeA1TToT(signalHeadName); 5324 } 5325 removeAssignment(b1TToTHead); 5326 layoutTurnout1.setSignalC1Name(signalHeadName); 5327 needRedraw = true; 5328 } 5329 } else { 5330 LayoutTurnout.Geometry assigned = isHeadAssignedHere(b1TToTHead, layoutTurnout1); 5331 if (assigned == LayoutTurnout.Geometry.NONE) { 5332 if (isHeadOnPanel(b1TToTHead) 5333 && isHeadAssignedAnywhere(b1TToTHead)) { 5334 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5335 Bundle.getMessage("SignalsError8", 5336 new Object[]{signalHeadName}), 5337 Bundle.getMessage("ErrorTitle"), 5338 JmriJOptionPane.ERROR_MESSAGE); 5339 return; 5340 } else { 5341 removeSignalHeadFromPanel(layoutTurnout1.getSignalC1Name()); 5342 removeAssignment(b1TToTHead); 5343 layoutTurnout1.setSignalC1Name(signalHeadName); 5344 } 5345 //} else if (assigned != C1) { 5346 //need to figure out what to do in this case. 5347 } 5348 } 5349 5350 signalHeadName = b2TToTSignalHeadComboBox.getSelectedItemDisplayName(); 5351 if (signalHeadName == null) { 5352 signalHeadName = ""; 5353 } 5354 if ((b2TToTHead != null) && setB2TToTHead.isSelected()) { 5355 if (isHeadOnPanel(b2TToTHead) 5356 && (b2TToTHead != getHeadFromName(layoutTurnout1.getSignalC2Name()))) { 5357 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5358 Bundle.getMessage("SignalsError6", 5359 new Object[]{signalHeadName}), 5360 Bundle.getMessage("ErrorTitle"), 5361 JmriJOptionPane.ERROR_MESSAGE); 5362 return; 5363 } else { 5364 removeSignalHeadFromPanel(layoutTurnout1.getSignalC2Name()); 5365 if (layoutTurnout1.getContinuingSense() == Turnout.CLOSED) { 5366 placeB2TToT(signalHeadName); 5367 } else { 5368 placeA2TToT(signalHeadName); 5369 } 5370 removeAssignment(b2TToTHead); 5371 layoutTurnout1.setSignalC2Name(signalHeadName); 5372 needRedraw = true; 5373 } 5374 } else if (b2TToTHead != null) { 5375 LayoutTurnout.Geometry assigned = isHeadAssignedHere(b2TToTHead, layoutTurnout1); 5376 if (assigned == LayoutTurnout.Geometry.NONE) { 5377 if (isHeadOnPanel(b2TToTHead) 5378 && isHeadAssignedAnywhere(b2TToTHead)) { 5379 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5380 Bundle.getMessage("SignalsError8", 5381 new Object[]{signalHeadName}), 5382 Bundle.getMessage("ErrorTitle"), 5383 JmriJOptionPane.ERROR_MESSAGE); 5384 return; 5385 } else { 5386 removeSignalHeadFromPanel(layoutTurnout1.getSignalC2Name()); 5387 removeAssignment(b2TToTHead); 5388 layoutTurnout1.setSignalC2Name(signalHeadName); 5389 } 5390 //} else if (assigned != C2) { 5391 //need to figure out what to do in this case. 5392 } 5393 } else { //b2TToTHead known to be null here 5394 removeSignalHeadFromPanel(layoutTurnout1.getSignalC2Name()); 5395 layoutTurnout1.setSignalC2Name(""); 5396 } 5397 5398 //signal heads on turnout 2 5399 signalHeadName = c1TToTSignalHeadComboBox.getSelectedItemDisplayName(); 5400 if (signalHeadName == null) { 5401 signalHeadName = ""; 5402 } 5403 if (setC1TToTHead.isSelected()) { 5404 if (isHeadOnPanel(c1TToTHead) 5405 && (c1TToTHead != getHeadFromName(layoutTurnout2.getSignalB1Name()))) { 5406 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5407 Bundle.getMessage("SignalsError6", 5408 new Object[]{signalHeadName}), 5409 Bundle.getMessage("ErrorTitle"), 5410 JmriJOptionPane.ERROR_MESSAGE); 5411 return; 5412 } else { 5413 removeSignalHeadFromPanel(layoutTurnout2.getSignalB1Name()); 5414 if (layoutTurnout2.getContinuingSense() == Turnout.CLOSED) { 5415 placeC1TToT(signalHeadName); 5416 } else { 5417 placeD1TToT(signalHeadName); 5418 } 5419 removeAssignment(c1TToTHead); 5420 layoutTurnout2.setSignalB1Name(signalHeadName); 5421 needRedraw = true; 5422 } 5423 } else { 5424 LayoutTurnout.Geometry assigned = isHeadAssignedHere(c1TToTHead, layoutTurnout2); 5425 if (assigned == LayoutTurnout.Geometry.NONE) { 5426 if (isHeadOnPanel(c1TToTHead) 5427 && isHeadAssignedAnywhere(c1TToTHead)) { 5428 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5429 Bundle.getMessage("SignalsError8", 5430 new Object[]{signalHeadName}), 5431 Bundle.getMessage("ErrorTitle"), 5432 JmriJOptionPane.ERROR_MESSAGE); 5433 return; 5434 } else { 5435 removeSignalHeadFromPanel(layoutTurnout2.getSignalB1Name()); 5436 removeAssignment(c1TToTHead); 5437 layoutTurnout2.setSignalB1Name(signalHeadName); 5438 } 5439 //} else if (assigned != B1) { 5440 //need to figure out what to do in this case. 5441 } 5442 } 5443 5444 signalHeadName = c2TToTSignalHeadComboBox.getSelectedItemDisplayName(); 5445 if (signalHeadName == null) { 5446 signalHeadName = ""; 5447 } 5448 if ((c2TToTHead != null) && setC2TToTHead.isSelected()) { 5449 if (isHeadOnPanel(c2TToTHead) 5450 && (c2TToTHead != getHeadFromName(layoutTurnout2.getSignalB2Name()))) { 5451 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5452 Bundle.getMessage("SignalsError6", 5453 new Object[]{signalHeadName}), 5454 Bundle.getMessage("ErrorTitle"), 5455 JmriJOptionPane.ERROR_MESSAGE); 5456 return; 5457 } else { 5458 removeSignalHeadFromPanel(layoutTurnout2.getSignalB2Name()); 5459 if (layoutTurnout2.getContinuingSense() == Turnout.CLOSED) { 5460 placeC2TToT(signalHeadName); 5461 } else { 5462 placeD2TToT(signalHeadName); 5463 } 5464 removeAssignment(c2TToTHead); 5465 layoutTurnout2.setSignalB2Name(signalHeadName); 5466 needRedraw = true; 5467 } 5468 } else if (c2TToTHead != null) { 5469 LayoutTurnout.Geometry assigned = isHeadAssignedHere(c2TToTHead, layoutTurnout2); 5470 if (assigned == LayoutTurnout.Geometry.NONE) { 5471 if (isHeadOnPanel(c2TToTHead) 5472 && isHeadAssignedAnywhere(c2TToTHead)) { 5473 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5474 Bundle.getMessage("SignalsError8", 5475 new Object[]{signalHeadName}), 5476 Bundle.getMessage("ErrorTitle"), 5477 JmriJOptionPane.ERROR_MESSAGE); 5478 return; 5479 } else { 5480 removeSignalHeadFromPanel(layoutTurnout2.getSignalB2Name()); 5481 removeAssignment(c2TToTHead); 5482 layoutTurnout2.setSignalB2Name(signalHeadName); 5483 } 5484 //} else if (assigned != B2) { 5485 //need to figure out what to do in this case. 5486 } 5487 } else { //c2TToTHead known to be null here 5488 removeSignalHeadFromPanel(layoutTurnout2.getSignalB2Name()); 5489 layoutTurnout2.setSignalB2Name(""); 5490 } 5491 5492 signalHeadName = d1TToTSignalHeadComboBox.getSelectedItemDisplayName(); 5493 if (signalHeadName == null) { 5494 signalHeadName = ""; 5495 } 5496 if (setD1TToTHead.isSelected()) { 5497 if (isHeadOnPanel(d1TToTHead) 5498 && (d1TToTHead != getHeadFromName(layoutTurnout2.getSignalC1Name()))) { 5499 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5500 Bundle.getMessage("SignalsError6", 5501 new Object[]{signalHeadName}), 5502 Bundle.getMessage("ErrorTitle"), 5503 JmriJOptionPane.ERROR_MESSAGE); 5504 return; 5505 } else { 5506 removeSignalHeadFromPanel(layoutTurnout2.getSignalC1Name()); 5507 if (layoutTurnout2.getContinuingSense() == Turnout.CLOSED) { 5508 placeD1TToT(signalHeadName); 5509 } else { 5510 placeC1TToT(signalHeadName); 5511 } 5512 removeAssignment(d1TToTHead); 5513 layoutTurnout2.setSignalC1Name(signalHeadName); 5514 needRedraw = true; 5515 } 5516 } else { 5517 LayoutTurnout.Geometry assigned = isHeadAssignedHere(d1TToTHead, layoutTurnout2); 5518 if (assigned == LayoutTurnout.Geometry.NONE) { 5519 if (isHeadOnPanel(d1TToTHead) 5520 && isHeadAssignedAnywhere(d1TToTHead)) { 5521 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5522 Bundle.getMessage("SignalsError8", 5523 new Object[]{signalHeadName}), 5524 Bundle.getMessage("ErrorTitle"), 5525 JmriJOptionPane.ERROR_MESSAGE); 5526 return; 5527 } else { 5528 removeSignalHeadFromPanel(layoutTurnout2.getSignalC1Name()); 5529 removeAssignment(d1TToTHead); 5530 layoutTurnout2.setSignalC1Name(signalHeadName); 5531 } 5532 //} else if (assigned != C1) { 5533 //need to figure out what to do in this case. 5534 } 5535 } 5536 5537 signalHeadName = d2TToTSignalHeadComboBox.getSelectedItemDisplayName(); 5538 if (signalHeadName == null) { 5539 signalHeadName = ""; 5540 } 5541 if ((d2TToTHead != null) && setD2TToTHead.isSelected()) { 5542 if (isHeadOnPanel(d2TToTHead) 5543 && (d2TToTHead != getHeadFromName(layoutTurnout2.getSignalC2Name()))) { 5544 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5545 Bundle.getMessage("SignalsError6", 5546 new Object[]{signalHeadName}), 5547 Bundle.getMessage("ErrorTitle"), 5548 JmriJOptionPane.ERROR_MESSAGE); 5549 return; 5550 } else { 5551 removeSignalHeadFromPanel(layoutTurnout2.getSignalC2Name()); 5552 if (layoutTurnout2.getContinuingSense() == Turnout.CLOSED) { 5553 placeD2TToT(signalHeadName); 5554 } else { 5555 placeC2TToT(signalHeadName); 5556 } 5557 removeAssignment(d2TToTHead); 5558 layoutTurnout2.setSignalC2Name(signalHeadName); 5559 needRedraw = true; 5560 } 5561 } else if (d2TToTHead != null) { 5562 LayoutTurnout.Geometry assigned = isHeadAssignedHere(d2TToTHead, layoutTurnout2); 5563 if (assigned == LayoutTurnout.Geometry.NONE) { 5564 if (isHeadOnPanel(d2TToTHead) 5565 && isHeadAssignedAnywhere(d2TToTHead)) { 5566 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5567 Bundle.getMessage("SignalsError8", 5568 new Object[]{signalHeadName}), 5569 Bundle.getMessage("ErrorTitle"), 5570 JmriJOptionPane.ERROR_MESSAGE); 5571 return; 5572 } else { 5573 removeSignalHeadFromPanel(layoutTurnout2.getSignalC2Name()); 5574 removeAssignment(d2TToTHead); 5575 layoutTurnout2.setSignalC2Name(signalHeadName); 5576 } 5577 //} else if (assigned != C2) { 5578 //need to figure out what to do in this case. 5579 } 5580 } else { //d2TToTHead known to be null here 5581 removeSignalHeadFromPanel(layoutTurnout2.getSignalC2Name()); 5582 layoutTurnout2.setSignalC2Name(""); 5583 } 5584 5585 //setup logic if requested 5586 if (setupA1TToTLogic.isSelected() || setupA2TToTLogic.isSelected()) { 5587 setLogicTToT(a1TToTHead, (TrackSegment) layoutTurnout2.getConnectB(), a2TToTHead, 5588 (TrackSegment) layoutTurnout2.getConnectC(), setupA1TToTLogic.isSelected(), 5589 setupA2TToTLogic.isSelected(), true, layoutTurnout2, layoutTurnout1); 5590 } 5591 if (setupB1TToTLogic.isSelected() || setupB2TToTLogic.isSelected()) { 5592 setLogicTToT(b1TToTHead, (TrackSegment) layoutTurnout2.getConnectB(), b2TToTHead, 5593 (TrackSegment) layoutTurnout2.getConnectC(), setupB1TToTLogic.isSelected(), 5594 setupB2TToTLogic.isSelected(), false, layoutTurnout2, layoutTurnout1); 5595 } 5596 if (setupC1TToTLogic.isSelected() || setupC2TToTLogic.isSelected()) { 5597 setLogicTToT(c1TToTHead, (TrackSegment) layoutTurnout1.getConnectB(), c2TToTHead, 5598 (TrackSegment) layoutTurnout1.getConnectC(), setupC1TToTLogic.isSelected(), 5599 setupC2TToTLogic.isSelected(), true, layoutTurnout1, layoutTurnout2); 5600 } 5601 if (setupD1TToTLogic.isSelected() || setupD2TToTLogic.isSelected()) { 5602 setLogicTToT(d1TToTHead, (TrackSegment) layoutTurnout1.getConnectB(), d2TToTHead, 5603 (TrackSegment) layoutTurnout1.getConnectC(), setupD1TToTLogic.isSelected(), 5604 setupD2TToTLogic.isSelected(), false, layoutTurnout1, layoutTurnout2); 5605 } 5606 //link the two turnouts 5607 layoutTurnout1.setLinkedTurnoutName(turnout2ComboBox.getSelectedItemDisplayName()); 5608 layoutTurnout1.setLinkType(LayoutTurnout.LinkType.THROAT_TO_THROAT); 5609 layoutTurnout2.setLinkedTurnoutName(turnout1ComboBox.getSelectedItemDisplayName()); 5610 layoutTurnout2.setLinkType(LayoutTurnout.LinkType.THROAT_TO_THROAT); 5611 //finish up 5612 setSignalsAtThroatToThroatTurnoutsOpenFlag = false; 5613 setSignalsAtThroatToThroatTurnoutsFrame.setVisible(false); 5614 if (needRedraw) { 5615 layoutEditor.redrawPanel(); 5616 needRedraw = false; 5617 layoutEditor.setDirty(); 5618 } 5619 } //setTToTSignalsDonePressed 5620 5621 private boolean getTToTSignalHeadInformation() { 5622 a1TToTHead = getSignalHeadFromEntry(a1TToTSignalHeadComboBox, true, setSignalsAtThroatToThroatTurnoutsFrame); 5623 if (a1TToTHead == null) { 5624 return false; 5625 } 5626 a2TToTHead = getSignalHeadFromEntry(a2TToTSignalHeadComboBox, false, setSignalsAtThroatToThroatTurnoutsFrame); 5627 b1TToTHead = getSignalHeadFromEntry(b1TToTSignalHeadComboBox, true, setSignalsAtThroatToThroatTurnoutsFrame); 5628 if (b1TToTHead == null) { 5629 return false; 5630 } 5631 b2TToTHead = getSignalHeadFromEntry(b2TToTSignalHeadComboBox, false, setSignalsAtThroatToThroatTurnoutsFrame); 5632 c1TToTHead = getSignalHeadFromEntry(c1TToTSignalHeadComboBox, true, setSignalsAtThroatToThroatTurnoutsFrame); 5633 if (c1TToTHead == null) { 5634 return false; 5635 } 5636 c2TToTHead = getSignalHeadFromEntry(c2TToTSignalHeadComboBox, false, setSignalsAtThroatToThroatTurnoutsFrame); 5637 d1TToTHead = getSignalHeadFromEntry(d1TToTSignalHeadComboBox, true, setSignalsAtThroatToThroatTurnoutsFrame); 5638 if (d1TToTHead == null) { 5639 return false; 5640 } 5641 d2TToTHead = getSignalHeadFromEntry(d2TToTSignalHeadComboBox, false, setSignalsAtThroatToThroatTurnoutsFrame); 5642 return true; 5643 } 5644 5645 private void placeA1TToT(String signalHeadName) { 5646 //place head near the continuing track of turnout 1 5647 if (testIcon == null) { 5648 testIcon = signalIconEditor.getIcon(0); 5649 } 5650 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 5651 5652 LayoutTurnoutView layoutTurnout1View = layoutEditor.getLayoutTurnoutView(layoutTurnout1); 5653 Point2D coordsB = layoutTurnout1View.getCoordsB(); 5654 Point2D coordsCenter = layoutTurnout1View.getCoordsCenter(); 5655 5656 double bDirDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsB, coordsCenter)); 5657 Point2D delta = new Point2D.Double(0.0, -shift); 5658 5659 delta = MathUtil.rotateDEG(delta, bDirDEG); 5660 Point2D where = MathUtil.add(coordsB, delta); 5661 setSignalHeadOnPanel(bDirDEG, signalHeadName, where); 5662 } 5663 5664 private void placeA2TToT(String signalHeadName) { 5665 if (testIcon == null) { 5666 testIcon = signalIconEditor.getIcon(0); 5667 } 5668 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 5669 5670 LayoutTurnoutView layoutTurnout1View = layoutEditor.getLayoutTurnoutView(layoutTurnout1); 5671 Point2D coordsB = layoutTurnout1View.getCoordsB(); 5672 Point2D coordsCenter = layoutTurnout1View.getCoordsCenter(); 5673 5674 double bDirDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsB, coordsCenter)); 5675 Point2D delta = new Point2D.Double(2.0 * shift, -shift); 5676 5677 delta = MathUtil.rotateDEG(delta, bDirDEG); 5678 Point2D where = MathUtil.add(coordsB, delta); 5679 setSignalHeadOnPanel(bDirDEG, signalHeadName, where); 5680 } 5681 5682 private void placeB1TToT(String signalHeadName) { 5683 if (testIcon == null) { 5684 testIcon = signalIconEditor.getIcon(0); 5685 } 5686 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 5687 5688 LayoutTurnoutView layoutTurnout1View = layoutEditor.getLayoutTurnoutView(layoutTurnout1); 5689 Point2D coordsB = layoutTurnout1View.getCoordsB(); 5690 Point2D coordsC = layoutTurnout1View.getCoordsC(); 5691 Point2D coordsCenter = layoutTurnout1View.getCoordsCenter(); 5692 5693 double bDirDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsB, coordsCenter)); 5694 double cDirDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsC, coordsCenter)); 5695 double diffDirDEG = MathUtil.diffAngleDEG(cDirDEG, bDirDEG); 5696 double shiftX = 0.0; 5697 if (diffDirDEG >= 0.0) { 5698 shiftX += shift * Math.cos(Math.toRadians(diffDirDEG)); 5699 } 5700 Point2D delta = new Point2D.Double(shiftX, -shift); 5701 5702 delta = MathUtil.rotateDEG(delta, cDirDEG); 5703 Point2D where = MathUtil.add(coordsC, delta); 5704 setSignalHeadOnPanel(cDirDEG, signalHeadName, where); 5705 } 5706 5707 private void placeB2TToT(String signalHeadName) { 5708 if (testIcon == null) { 5709 testIcon = signalIconEditor.getIcon(0); 5710 } 5711 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 5712 5713 LayoutTurnoutView layoutTurnout1View = layoutEditor.getLayoutTurnoutView(layoutTurnout1); 5714 Point2D coordsB = layoutTurnout1View.getCoordsB(); 5715 Point2D coordsC = layoutTurnout1View.getCoordsC(); 5716 Point2D coordsCenter = layoutTurnout1View.getCoordsCenter(); 5717 5718 double bDirDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsB, coordsCenter)); 5719 double cDirDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsC, coordsCenter)); 5720 double diffDirDEG = MathUtil.diffAngleDEG(cDirDEG, bDirDEG); 5721 double shiftX = 2.0 * shift; 5722 if (diffDirDEG >= 0.0) { 5723 shiftX += shift * Math.cos(Math.toRadians(diffDirDEG)); 5724 } 5725 Point2D delta = new Point2D.Double(shiftX, -shift); 5726 5727 delta = MathUtil.rotateDEG(delta, cDirDEG); 5728 Point2D where = MathUtil.add(coordsC, delta); 5729 setSignalHeadOnPanel(cDirDEG, signalHeadName, where); 5730 } 5731 5732 private void placeC1TToT(String signalHeadName) { 5733 if (testIcon == null) { 5734 testIcon = signalIconEditor.getIcon(0); 5735 } 5736 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 5737 5738 LayoutTurnoutView layoutTurnout2View = layoutEditor.getLayoutTurnoutView(layoutTurnout2); 5739 Point2D coordsB = layoutTurnout2View.getCoordsB(); 5740 Point2D coordsCenter = layoutTurnout2View.getCoordsCenter(); 5741 5742 double bDirDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsB, coordsCenter)); 5743 Point2D delta = new Point2D.Double(0.0, -shift); 5744 5745 delta = MathUtil.rotateDEG(delta, bDirDEG); 5746 Point2D where = MathUtil.add(coordsB, delta); 5747 setSignalHeadOnPanel(bDirDEG, signalHeadName, where); 5748 } 5749 5750 private void placeC2TToT(String signalHeadName) { 5751 if (testIcon == null) { 5752 testIcon = signalIconEditor.getIcon(0); 5753 } 5754 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 5755 5756 LayoutTurnoutView layoutTurnout2View = layoutEditor.getLayoutTurnoutView(layoutTurnout2); 5757 Point2D coordsB = layoutTurnout2View.getCoordsB(); 5758 Point2D coordsCenter = layoutTurnout2View.getCoordsCenter(); 5759 5760 double bDirDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsB, coordsCenter)); 5761 Point2D delta = new Point2D.Double(2.0 * shift, -shift); 5762 5763 delta = MathUtil.rotateDEG(delta, bDirDEG); 5764 Point2D where = MathUtil.add(coordsB, delta); 5765 setSignalHeadOnPanel(bDirDEG, signalHeadName, where); 5766 } 5767 5768 private void placeD1TToT(String signalHeadName) { 5769 if (testIcon == null) { 5770 testIcon = signalIconEditor.getIcon(0); 5771 } 5772 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 5773 5774 LayoutTurnoutView layoutTurnout2View = layoutEditor.getLayoutTurnoutView(layoutTurnout2); 5775 Point2D coordsB = layoutTurnout2View.getCoordsB(); 5776 Point2D coordsC = layoutTurnout2View.getCoordsC(); 5777 Point2D coordsCenter = layoutTurnout2View.getCoordsCenter(); 5778 5779 double bDirDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsB, coordsCenter)); 5780 double cDirDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsC, coordsCenter)); 5781 double diffDirDEG = MathUtil.diffAngleDEG(cDirDEG, bDirDEG); 5782 double shiftX = 0.0; 5783 if (diffDirDEG >= 0.0) { 5784 shiftX += shift * Math.cos(Math.toRadians(diffDirDEG)); 5785 } 5786 Point2D delta = new Point2D.Double(shiftX, -shift); 5787 5788 delta = MathUtil.rotateDEG(delta, cDirDEG); 5789 Point2D where = MathUtil.add(coordsC, delta); 5790 setSignalHeadOnPanel(cDirDEG, signalHeadName, where); 5791 } 5792 5793 private void placeD2TToT(String signalHeadName) { 5794 if (testIcon == null) { 5795 testIcon = signalIconEditor.getIcon(0); 5796 } 5797 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 5798 5799 LayoutTurnoutView layoutTurnout2View = layoutEditor.getLayoutTurnoutView(layoutTurnout2); 5800 Point2D coordsB = layoutTurnout2View.getCoordsB(); 5801 Point2D coordsC = layoutTurnout2View.getCoordsC(); 5802 Point2D coordsCenter = layoutTurnout2View.getCoordsCenter(); 5803 5804 double bDirDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsB, coordsCenter)); 5805 double cDirDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsC, coordsCenter)); 5806 double diffDirDEG = MathUtil.diffAngleDEG(cDirDEG, bDirDEG); 5807 double shiftX = 2.0 * shift; 5808 if (diffDirDEG >= 0.0) { 5809 shiftX += shift * Math.cos(Math.toRadians(diffDirDEG)); 5810 } 5811 Point2D delta = new Point2D.Double(shiftX, -shift); 5812 5813 delta = MathUtil.rotateDEG(delta, cDirDEG); 5814 Point2D where = MathUtil.add(coordsC, delta); 5815 setSignalHeadOnPanel(cDirDEG, signalHeadName, where); 5816 } 5817 5818 @SuppressWarnings("null") 5819 private void setLogicTToT(SignalHead head, TrackSegment track1, SignalHead secondHead, TrackSegment track2, 5820 boolean setup1, boolean setup2, boolean continuing, 5821 LayoutTurnout farTurnout, LayoutTurnout nearTurnout) { 5822 //initialize common components and ensure all is defined 5823 LayoutBlock connectorBlock = connectorTrack.getLayoutBlock(); 5824 LayoutBlock nearTurnoutBlock = nearTurnout.getLayoutBlock(); 5825 LayoutBlock farTurnoutBlock = farTurnout.getLayoutBlock(); 5826 Sensor connectorOccupancy = null; 5827 if ((connectorBlock == null) || (nearTurnoutBlock == null) || (farTurnoutBlock == null)) { 5828 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5829 Bundle.getMessage("InfoMessage6"), 5830 Bundle.getMessage("MessageTitle"), 5831 JmriJOptionPane.INFORMATION_MESSAGE); 5832 return; 5833 } 5834 connectorOccupancy = connectorBlock.getOccupancySensor(); 5835 if (connectorOccupancy == null) { 5836 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5837 Bundle.getMessage("InfoMessage4", 5838 new Object[]{connectorBlock.getUserName()}), 5839 Bundle.getMessage("MessageTitle"), 5840 JmriJOptionPane.INFORMATION_MESSAGE); 5841 return; 5842 } 5843 //setup signal head for continuing track of far turnout (or both tracks of far turnout) 5844 if ((track1 == null) && setup1) { 5845 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5846 Bundle.getMessage("InfoMessage7"), 5847 Bundle.getMessage("MessageTitle"), 5848 JmriJOptionPane.INFORMATION_MESSAGE); 5849 return; 5850 } 5851 Sensor occupancy = null; 5852 SignalHead nextHead = null; 5853 if ((track1 != null) && setup1) { 5854 LayoutBlock block = track1.getLayoutBlock(); 5855 if (block == null) { 5856 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5857 Bundle.getMessage("InfoMessage6"), 5858 Bundle.getMessage("MessageTitle"), 5859 JmriJOptionPane.INFORMATION_MESSAGE); 5860 return; 5861 } 5862 occupancy = block.getOccupancySensor(); 5863 if (occupancy == null) { 5864 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5865 Bundle.getMessage("InfoMessage4", 5866 new Object[]{block.getUserName()}), 5867 Bundle.getMessage("MessageTitle"), 5868 JmriJOptionPane.INFORMATION_MESSAGE); 5869 return; 5870 } 5871 nextHead = getNextSignalFromObject(track1, farTurnout, 5872 head.getSystemName(), setSignalsAtThroatToThroatTurnoutsFrame); 5873 if ((nextHead == null) && (!reachedEndBumper())) { 5874 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 5875 Bundle.getMessage("InfoMessage5", 5876 new Object[]{block.getUserName()}), 5877 Bundle.getMessage("MessageTitle"), 5878 JmriJOptionPane.INFORMATION_MESSAGE); 5879 return; 5880 } 5881 if (secondHead != null) { 5882 //this head signals only the continuing track of the far turnout 5883 if (!initializeBlockBossLogic(head.getDisplayName())) { 5884 return; 5885 } 5886 logic.setMode(BlockBossLogic.TRAILINGMAIN); 5887 logic.setTurnout(farTurnout.getTurnout().getDisplayName()); 5888 logic.setSensor1(occupancy.getDisplayName()); 5889 if (occupancy != connectorOccupancy) { 5890 logic.setSensor2(connectorOccupancy.getDisplayName()); 5891 } 5892 if (nextHead != null) { 5893 logic.setWatchedSignal1(nextHead.getDisplayName(), false); 5894 } 5895 if (auxSignal != null) { 5896 logic.setWatchedSignal1Alt(auxSignal.getDisplayName()); 5897 } 5898 String nearSensorName = setupNearLogix(nearTurnout, continuing, head); 5899 addNearSensorToLogic(nearSensorName); 5900 finalizeBlockBossLogic(); 5901 } 5902 } 5903 if ((secondHead != null) && !setup2) { 5904 return; 5905 } 5906 SignalHead savedAuxSignal = auxSignal; 5907 if (track2 == null) { 5908 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5909 Bundle.getMessage("InfoMessage7"), 5910 Bundle.getMessage("MessageTitle"), 5911 JmriJOptionPane.INFORMATION_MESSAGE); 5912 return; 5913 } 5914 LayoutBlock block2 = track2.getLayoutBlock(); 5915 if (block2 == null) { 5916 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5917 Bundle.getMessage("InfoMessage6"), 5918 Bundle.getMessage("MessageTitle"), 5919 JmriJOptionPane.INFORMATION_MESSAGE); 5920 return; 5921 } 5922 Sensor occupancy2 = block2.getOccupancySensor(); 5923 if (occupancy2 == null) { 5924 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5925 Bundle.getMessage("InfoMessage4", 5926 new Object[]{block2.getUserName()}), 5927 Bundle.getMessage("MessageTitle"), 5928 JmriJOptionPane.INFORMATION_MESSAGE); 5929 return; 5930 } 5931 SignalHead nextHead2 = null; 5932 if (secondHead != null) { 5933 nextHead2 = getNextSignalFromObject(track2, 5934 farTurnout, secondHead.getSystemName(), setSignalsAtThroatToThroatTurnoutsFrame); 5935 if ((nextHead2 == null) && (!reachedEndBumper())) { 5936 JmriJOptionPane.showMessageDialog(setSignalsAtThroatToThroatTurnoutsFrame, 5937 Bundle.getMessage("InfoMessage5", 5938 new Object[]{block2.getUserName()}), 5939 Bundle.getMessage("MessageTitle"), 5940 JmriJOptionPane.INFORMATION_MESSAGE); 5941 return; 5942 } 5943 } 5944 if ((secondHead == null) && (track1 != null) && setup1) { 5945 if (!initializeBlockBossLogic(head.getDisplayName())) { 5946 return; 5947 } 5948 logic.setMode(BlockBossLogic.FACING); 5949 logic.setTurnout(farTurnout.getTurnout().getDisplayName()); 5950 logic.setWatchedSensor1(occupancy.getDisplayName()); 5951 logic.setWatchedSensor2(occupancy2.getDisplayName()); 5952 logic.setSensor2(connectorOccupancy.getDisplayName()); 5953 if (nextHead != null) { 5954 logic.setWatchedSignal1(nextHead.getDisplayName(), false); 5955 } 5956 if (savedAuxSignal != null) { 5957 logic.setWatchedSignal1Alt(savedAuxSignal.getDisplayName()); 5958 } 5959 if (nextHead2 != null) { 5960 logic.setWatchedSignal2(nextHead2.getDisplayName()); 5961 } 5962 if (auxSignal != null) { 5963 logic.setWatchedSignal2Alt(auxSignal.getDisplayName()); 5964 } 5965 String nearSensorName = setupNearLogix(nearTurnout, continuing, head); 5966 addNearSensorToLogic(nearSensorName); 5967 logic.setLimitSpeed2(true); 5968 finalizeBlockBossLogic(); 5969 } else if ((secondHead != null) && setup2) { 5970 if (!initializeBlockBossLogic(secondHead.getDisplayName())) { 5971 return; 5972 } 5973 logic.setMode(BlockBossLogic.TRAILINGDIVERGING); 5974 logic.setTurnout(farTurnout.getTurnout().getDisplayName()); 5975 logic.setSensor1(occupancy2.getDisplayName()); 5976 if (occupancy2 != connectorOccupancy) { 5977 logic.setSensor2(connectorOccupancy.getDisplayName()); 5978 } 5979 if (nextHead2 != null) { 5980 logic.setWatchedSignal1(nextHead2.getDisplayName(), false); 5981 } 5982 if (auxSignal != null) { 5983 logic.setWatchedSignal1Alt(auxSignal.getDisplayName()); 5984 } 5985 String nearSensorName = setupNearLogix(nearTurnout, continuing, head); 5986 addNearSensorToLogic(nearSensorName); 5987 logic.setLimitSpeed2(true); 5988 finalizeBlockBossLogic(); 5989 } 5990 } //setLogicTToT 5991 5992 /* 5993 * Sets up a Logix to set a sensor active if a turnout is set against 5994 * a track. This routine creates an internal sensor for the purpose. 5995 * Note: The sensor and logix are named pref + S or pref + X followed by TTT_X_HHH where 5996 * TTT is the system name of the turnout, X is either C or T depending 5997 * on "continuing", and HHH is the system name of the signal head. 5998 * Note: If there is any problem, a string of "" is returned, and a warning 5999 * message is issued. 6000 */ 6001 private String setupNearLogix(LayoutTurnout nearTurnout, boolean continuing, 6002 SignalHead head) { 6003 String turnoutName = nearTurnout.getTurnout().getSystemName(); 6004 String namer = turnoutName + "_T_" + head.getSystemName(); 6005 if (!continuing) { 6006 namer = turnoutName + "_C_" + head.getSystemName(); 6007 } 6008 String pref = InstanceManager.getDefault(jmri.LogixManager.class).getSystemPrefix(); 6009 String sensorName = pref + "S" + namer; 6010 String logixName = pref + "X" + namer; 6011 try { 6012 InstanceManager.sensorManagerInstance().provideSensor(sensorName); 6013 } catch (IllegalArgumentException ex) { 6014 log.error("Trouble creating sensor {} while setting up Logix.", sensorName); 6015 return ""; 6016 6017 } 6018 if (InstanceManager.getDefault(LogixManager.class).getBySystemName(logixName) == null) { 6019 //Logix does not exist, create it 6020 Logix x = InstanceManager.getDefault(LogixManager.class).createNewLogix(logixName, ""); 6021 if (x == null) { 6022 log.error("Trouble creating logix {} while setting up signal logic.", logixName); 6023 return ""; 6024 } 6025 String cName = x.getSystemName() + "C1"; 6026 Conditional c = InstanceManager.getDefault(ConditionalManager.class). 6027 createNewConditional(cName, ""); 6028 if (c == null) { 6029 log.error("Trouble creating conditional {} while setting up Logix.", cName); 6030 return ""; 6031 } 6032 Conditional.Type type = Conditional.Type.TURNOUT_THROWN; 6033 if (!continuing) { 6034 type = Conditional.Type.TURNOUT_CLOSED; 6035 } 6036 List<ConditionalVariable> variableList = c.getCopyOfStateVariables(); 6037 variableList.add(new ConditionalVariable(false, Conditional.Operator.AND, 6038 type, turnoutName, true)); 6039 c.setStateVariables(variableList); 6040 List<ConditionalAction> actionList = c.getCopyOfActions(); 6041 actionList.add(new DefaultConditionalAction(Conditional.ACTION_OPTION_ON_CHANGE_TO_TRUE, 6042 Conditional.Action.SET_SENSOR, sensorName, 6043 Sensor.ACTIVE, "")); 6044 actionList.add(new DefaultConditionalAction(Conditional.ACTION_OPTION_ON_CHANGE_TO_FALSE, 6045 Conditional.Action.SET_SENSOR, sensorName, 6046 Sensor.INACTIVE, "")); 6047 c.setAction(actionList); // string data 6048 x.addConditional(cName, -1); 6049 x.activateLogix(); 6050 } 6051 return sensorName; 6052 } 6053 6054 /* 6055 * Adds the sensor specified to the open BlockBossLogic, provided it is not already there and 6056 * provided there is an open slot. If 'name' is null or empty, returns without doing anything. 6057 */ 6058 private void addNearSensorToLogic(String name) { 6059 if ((name != null) && !name.isEmpty()) { 6060 //return if a sensor by this name is already present 6061 if ((logic.getSensor1() != null) && (logic.getSensor1().equals(name))) { 6062 return; 6063 } 6064 if ((logic.getSensor2() != null) && (logic.getSensor2().equals(name))) { 6065 return; 6066 } 6067 if ((logic.getSensor3() != null) && (logic.getSensor3().equals(name))) { 6068 return; 6069 } 6070 if ((logic.getSensor4() != null) && (logic.getSensor4().equals(name))) { 6071 return; 6072 } 6073 if ((logic.getSensor5() != null) && (logic.getSensor5().equals(name))) { 6074 return; 6075 } 6076 //add in the first available slot 6077 if (logic.getSensor1() == null) { 6078 logic.setSensor1(name); 6079 } else if (logic.getSensor2() == null) { 6080 logic.setSensor2(name); 6081 } else if (logic.getSensor3() == null) { 6082 logic.setSensor3(name); 6083 } else if (logic.getSensor4() == null) { 6084 logic.setSensor4(name); 6085 } else if (logic.getSensor5() == null) { 6086 logic.setSensor5(name); 6087 } else { 6088 log.error("Error - could not add sensor to SSL for signal head {}", logic.getDrivenSignal()); 6089 } 6090 } 6091 } 6092 6093 /*=========================*\ 6094 |* setSignalsAt3WayTurnout *| 6095 \*=========================*/ 6096 /** 6097 * Tool to set signals at a three-way turnout, including placing the signal 6098 * icons and setup of signal logic for each signal head 6099 * <p> 6100 * This tool can only be accessed from the Tools menu. There is no access 6101 * from a turnout pop-up menu. 6102 * <p> 6103 * This tool requires a situation where two turnouts are connected to model 6104 * a 3-way turnout, with the throat of the second turnout connected to the 6105 * continuing leg of the first turnout by a very short track segment. The 6106 * actual length of the track segment is not tested. If this situation is 6107 * not found, and error message is sent to the user. 6108 * <p> 6109 * This tool assumes two turnouts connected with the throat of the second 6110 * turnout connected to the continuing leg of the first turnou, as used to 6111 * represent a 3-way turnout. The turnouts may be either left-handed, or 6112 * right-handed, or any pair of these. This tool also assumes that there are 6113 * no signals between the two turnouts. Signal heads are allowed/required at 6114 * the continuing leg of the second turnout, at each of the diverging legs, 6115 * and at the throat. At the throat, either one or three heads are provided 6116 * for. So four or six heads will be placed. 6117 * <p> 6118 * This tool assumes that each of the four tracks, the continuing, the two 6119 * diverging, and the throat is contained in a different block. The two 6120 * turnouts used to model the 3-way turnout must be in the same block. 6121 * Things work best if the two turnouts are in the same block as the track 6122 * connecting at the throat, or if the two turnouts are in their own 6123 * separate block, either works fine. 6124 */ 6125 //operational variables for Set Signals at 3-Way Turnout tool 6126 private JmriJFrame setSignalsAt3WayTurnoutFrame = null; 6127 private boolean setSignalsAt3WayTurnoutOpenFlag = false; 6128 private boolean setSignalsAt3WayTurnoutFromMenuFlag = false; 6129 6130 private JLabel turnoutANameLabel = null; 6131 private JLabel turnoutBNameLabel = null; 6132 6133 private final NamedBeanComboBox<Turnout> turnoutAComboBox = new NamedBeanComboBox<>( 6134 InstanceManager.turnoutManagerInstance(), 6135 null, DisplayOptions.DISPLAYNAME); 6136 private final NamedBeanComboBox<Turnout> turnoutBComboBox = new NamedBeanComboBox<>( 6137 InstanceManager.turnoutManagerInstance(), 6138 null, DisplayOptions.DISPLAYNAME); 6139 6140 private final NamedBeanComboBox<SignalHead> a1_3WaySignalHeadComboBox = new NamedBeanComboBox<>( 6141 InstanceManager.getDefault(SignalHeadManager.class 6142 ), 6143 null, DisplayOptions.DISPLAYNAME); 6144 private final NamedBeanComboBox<SignalHead> a2_3WaySignalHeadComboBox = new NamedBeanComboBox<>( 6145 InstanceManager.getDefault(SignalHeadManager.class 6146 ), 6147 null, DisplayOptions.DISPLAYNAME); 6148 private final NamedBeanComboBox<SignalHead> a3_3WaySignalHeadComboBox = new NamedBeanComboBox<>( 6149 InstanceManager.getDefault(SignalHeadManager.class 6150 ), 6151 null, DisplayOptions.DISPLAYNAME); 6152 private final NamedBeanComboBox<SignalHead> b_3WaySignalHeadComboBox = new NamedBeanComboBox<>( 6153 InstanceManager.getDefault(SignalHeadManager.class 6154 ), 6155 null, DisplayOptions.DISPLAYNAME); 6156 private final NamedBeanComboBox<SignalHead> c_3WaySignalHeadComboBox = new NamedBeanComboBox<>( 6157 InstanceManager.getDefault(SignalHeadManager.class 6158 ), 6159 null, DisplayOptions.DISPLAYNAME); 6160 private final NamedBeanComboBox<SignalHead> d_3WaySignalHeadComboBox = new NamedBeanComboBox<>( 6161 InstanceManager.getDefault(SignalHeadManager.class 6162 ), 6163 null, DisplayOptions.DISPLAYNAME); 6164 6165 private final JCheckBox setA13WayHead = new JCheckBox(Bundle.getMessage("PlaceHead")); 6166 private final JCheckBox setupA13WayLogic = new JCheckBox(Bundle.getMessage("SetLogic")); 6167 private final JCheckBox setA23WayHead = new JCheckBox(Bundle.getMessage("PlaceHead")); 6168 private final JCheckBox setupA23WayLogic = new JCheckBox(Bundle.getMessage("SetLogic")); 6169 private final JCheckBox setA33WayHead = new JCheckBox(Bundle.getMessage("PlaceHead")); 6170 private final JCheckBox setupA33WayLogic = new JCheckBox(Bundle.getMessage("SetLogic")); 6171 private final JCheckBox setB3WayHead = new JCheckBox(Bundle.getMessage("PlaceHead")); 6172 private final JCheckBox setupB3WayLogic = new JCheckBox(Bundle.getMessage("SetLogic")); 6173 private final JCheckBox setC3WayHead = new JCheckBox(Bundle.getMessage("PlaceHead")); 6174 private final JCheckBox setupC3WayLogic = new JCheckBox(Bundle.getMessage("SetLogic")); 6175 private final JCheckBox setD3WayHead = new JCheckBox(Bundle.getMessage("PlaceHead")); 6176 private final JCheckBox setupD3WayLogic = new JCheckBox(Bundle.getMessage("SetLogic")); 6177 private JButton getSaved3WaySignalHeads = null; 6178 private JButton change3WaySignalIcon = null; 6179 private JButton set3WaySignalsDone = null; 6180 private JButton set3WaySignalsCancel = null; 6181 private LayoutTurnout layoutTurnoutA = null; 6182 private LayoutTurnout layoutTurnoutB = null; 6183 private Turnout turnoutA = null; 6184 private Turnout turnoutB = null; 6185 //private TrackSegment conTrack = null; 6186 private SignalHead a13WayHead = null; //saved in A1 of Turnout A - Throat - continuing 6187 private SignalHead a23WayHead = null; //saved in A2 of Turnout A - Throat - diverging A (optional) 6188 private SignalHead a33WayHead = null; //saved in A3 of Turnout A - Throat - diverging B (optional) 6189 private SignalHead b3WayHead = null; //saved in C1 of Turnout A - at diverging A 6190 private SignalHead c3WayHead = null; //saved in B1 of Turnout B - at continuing 6191 private SignalHead d3WayHead = null; //saved in C1 of Turnout B - at diverging B 6192 6193 public void setSignalsAt3WayTurnoutFromMenu( 6194 @Nonnull String aName, @Nonnull String bName, 6195 @Nonnull MultiIconEditor theEditor, @Nonnull JFrame theFrame) { 6196 Turnout ta = InstanceManager.getDefault(jmri.TurnoutManager.class).getTurnout(aName); 6197 Turnout tb = InstanceManager.getDefault(jmri.TurnoutManager.class).getTurnout(bName); 6198 turnoutAComboBox.setSelectedItem(ta); 6199 turnoutBComboBox.setSelectedItem(tb); 6200 a1_3WaySignalHeadComboBox.setSelectedItem(null); 6201 a2_3WaySignalHeadComboBox.setSelectedItem(null); 6202 a3_3WaySignalHeadComboBox.setSelectedItem(null); 6203 b_3WaySignalHeadComboBox.setSelectedItem(null); 6204 c_3WaySignalHeadComboBox.setSelectedItem(null); 6205 d_3WaySignalHeadComboBox.setSelectedItem(null); 6206 setSignalsAt3WayTurnoutFromMenuFlag = true; 6207 setSignalsAt3WayTurnout(theEditor, theFrame); 6208 setSignalsAt3WayTurnoutFromMenuFlag = false; 6209 } 6210 6211 public void setSignalsAt3WayTurnout(@Nonnull MultiIconEditor theEditor, 6212 @Nonnull JFrame theFrame) { 6213 signalIconEditor = theEditor; 6214 signalFrame = theFrame; 6215 6216 //Initialize if needed 6217 if (setSignalsAt3WayTurnoutFrame == null) { 6218 setSignalsAt3WayTurnoutOpenFlag = false; 6219 setSignalsAt3WayTurnoutFrame = new JmriJFrame(Bundle.getMessage("SignalsAt3WayTurnout"), false, true); 6220 oneFrameToRuleThemAll(setSignalsAt3WayTurnoutFrame); 6221 setSignalsAt3WayTurnoutFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 6222 setSignalsAt3WayTurnoutFrame.addHelpMenu("package.jmri.jmrit.display.SetSignalsAt3WayTurnout", true); 6223 setSignalsAt3WayTurnoutFrame.setLocation(70, 30); 6224 Container theContentPane = setSignalsAt3WayTurnoutFrame.getContentPane(); 6225 theContentPane.setLayout(new BoxLayout(theContentPane, BoxLayout.Y_AXIS)); 6226 6227 JPanel panel1A = new JPanel(new FlowLayout()); 6228 turnoutANameLabel = new JLabel(Bundle.getMessage("MakeLabel", Bundle.getMessage("TurnoutAName"))); 6229 panel1A.add(turnoutANameLabel); 6230 panel1A.add(turnoutAComboBox); 6231 turnoutAComboBox.setToolTipText(Bundle.getMessage("SignalsTurnoutNameHint")); 6232 theContentPane.add(panel1A); 6233 6234 JPanel panel1B = new JPanel(new FlowLayout()); 6235 turnoutBNameLabel = new JLabel(Bundle.getMessage("MakeLabel", Bundle.getMessage("TurnoutBName"))); 6236 panel1B.add(turnoutBNameLabel); 6237 panel1B.add(turnoutBComboBox); 6238 turnoutBComboBox.setToolTipText(Bundle.getMessage("SignalsTurnoutNameHint")); 6239 theContentPane.add(panel1B); 6240 theContentPane.add(new JSeparator(JSeparator.HORIZONTAL)); 6241 //Provide for retrieval of names of previously saved signal heads 6242 6243 JPanel panel2 = new JPanel(new FlowLayout()); 6244 JLabel shTitle = new JLabel(Bundle.getMessage("SignalHeads")); 6245 panel2.add(shTitle); 6246 panel2.add(new JLabel(" ")); 6247 panel2.add(getSaved3WaySignalHeads = new JButton(Bundle.getMessage("GetSaved"))); 6248 getSaved3WaySignalHeads.addActionListener(this::getSaved3WaySignals); 6249 getSaved3WaySignalHeads.setToolTipText(Bundle.getMessage("GetSavedHint")); 6250 theContentPane.add(panel2); 6251 6252 theContentPane.add(new JSeparator(JSeparator.HORIZONTAL)); 6253 JPanel panel2a = new JPanel(new FlowLayout()); 6254 panel2a.add(new JLabel(" ")); 6255 panel2a.add(setPlaceAllHeads); 6256 setPlaceAllHeads.setToolTipText(Bundle.getMessage("PlaceAllHeadsHint")); 6257 setPlaceAllHeads.addActionListener((ActionEvent e) -> { 6258 boolean isSelected = setPlaceAllHeads.isSelected(); 6259 //(de)select all checkboxes 6260 setA13WayHead.setSelected(isSelected); 6261 setA23WayHead.setSelected(isSelected); 6262 setA33WayHead.setSelected(isSelected); 6263 setB3WayHead.setSelected(isSelected); 6264 setC3WayHead.setSelected(isSelected); 6265 setD3WayHead.setSelected(isSelected); 6266 }); 6267 panel2a.add(new JLabel(" ")); 6268 panel2a.add(setupAllLogic); 6269 setupAllLogic.setToolTipText(Bundle.getMessage("SetAllLogicHint")); 6270 setupAllLogic.addActionListener((ActionEvent e) -> { 6271 boolean isSelected = setupAllLogic.isSelected(); 6272 //(de)select all checkboxes 6273 setupA13WayLogic.setSelected(isSelected); 6274 setupA23WayLogic.setSelected(isSelected); 6275 setupA33WayLogic.setSelected(isSelected); 6276 setupB3WayLogic.setSelected(isSelected); 6277 setupC3WayLogic.setSelected(isSelected); 6278 setupD3WayLogic.setSelected(isSelected); 6279 }); 6280 theContentPane.add(panel2a); 6281 theContentPane.add(new JSeparator(JSeparator.HORIZONTAL)); 6282 6283 //Signal heads located at turnout A 6284 JPanel panel20 = new JPanel(new FlowLayout()); 6285 panel20.add(new JLabel(Bundle.getMessage("SignalLocated") 6286 + " " + Bundle.getMessage("BeanNameTurnout") + " A ")); 6287 theContentPane.add(panel20); 6288 6289 JPanel panel21 = new JPanel(new FlowLayout()); 6290 panel21.add(new JLabel(Bundle.getMessage("MakeLabel", 6291 throatString + " - " 6292 + continuingString))); 6293 panel21.add(a1_3WaySignalHeadComboBox); 6294 a1_3WaySignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 6295 theContentPane.add(panel21); 6296 6297 JPanel panel22 = new JPanel(new FlowLayout()); 6298 panel22.add(new JLabel(" ")); 6299 panel22.add(setA13WayHead); 6300 setA13WayHead.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 6301 panel22.add(new JLabel(" ")); 6302 panel22.add(setupA13WayLogic); 6303 setupA13WayLogic.setToolTipText(Bundle.getMessage("SetLogicHint")); 6304 theContentPane.add(panel22); 6305 6306 JPanel panel23 = new JPanel(new FlowLayout()); 6307 panel23.add(new JLabel(Bundle.getMessage("MakeLabel", 6308 throatString + " - " 6309 + divergingAString))); 6310 panel23.add(a2_3WaySignalHeadComboBox); 6311 a2_3WaySignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 6312 theContentPane.add(panel23); 6313 6314 JPanel panel24 = new JPanel(new FlowLayout()); 6315 panel24.add(new JLabel(" ")); 6316 panel24.add(setA23WayHead); 6317 setA23WayHead.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 6318 panel24.add(new JLabel(" ")); 6319 panel24.add(setupA23WayLogic); 6320 setupA23WayLogic.setToolTipText(Bundle.getMessage("SetLogicHint")); 6321 theContentPane.add(panel24); 6322 6323 JPanel panel25 = new JPanel(new FlowLayout()); 6324 panel25.add(new JLabel(Bundle.getMessage("MakeLabel", 6325 throatString + " - " 6326 + divergingBString))); 6327 panel25.add(a3_3WaySignalHeadComboBox); 6328 a3_3WaySignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 6329 theContentPane.add(panel25); 6330 6331 JPanel panel26 = new JPanel(new FlowLayout()); 6332 panel26.add(new JLabel(" ")); 6333 panel26.add(setA33WayHead); 6334 setA33WayHead.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 6335 panel26.add(new JLabel(" ")); 6336 panel26.add(setupA33WayLogic); 6337 setupA33WayLogic.setToolTipText(Bundle.getMessage("SetLogicHint")); 6338 theContentPane.add(panel26); 6339 6340 JPanel panel31 = new JPanel(new FlowLayout()); 6341 panel31.add(new JLabel(Bundle.getMessage("MakeLabel", 6342 divergingBString))); 6343 panel31.add(b_3WaySignalHeadComboBox); 6344 b_3WaySignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 6345 theContentPane.add(panel31); 6346 6347 JPanel panel32 = new JPanel(new FlowLayout()); 6348 panel32.add(new JLabel(" ")); 6349 panel32.add(setB3WayHead); 6350 setB3WayHead.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 6351 panel32.add(new JLabel(" ")); 6352 panel32.add(setupB3WayLogic); 6353 setupB3WayLogic.setToolTipText(Bundle.getMessage("SetLogicHint")); 6354 theContentPane.add(panel32); 6355 theContentPane.add(new JSeparator(JSeparator.HORIZONTAL)); 6356 //Signal heads located at turnout B 6357 6358 JPanel panel40 = new JPanel(new FlowLayout()); 6359 panel40.add(new JLabel(Bundle.getMessage("SignalLocated") 6360 + " " + Bundle.getMessage("BeanNameTurnout") + " B ")); 6361 theContentPane.add(panel40); 6362 6363 JPanel panel41 = new JPanel(new FlowLayout()); 6364 panel41.add(new JLabel(Bundle.getMessage("MakeLabel", 6365 continuingString))); 6366 panel41.add(c_3WaySignalHeadComboBox); 6367 c_3WaySignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 6368 theContentPane.add(panel41); 6369 6370 JPanel panel42 = new JPanel(new FlowLayout()); 6371 panel42.add(new JLabel(" ")); 6372 panel42.add(setC3WayHead); 6373 setC3WayHead.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 6374 panel42.add(new JLabel(" ")); 6375 panel42.add(setupC3WayLogic); 6376 setupC3WayLogic.setToolTipText(Bundle.getMessage("SetLogicHint")); 6377 theContentPane.add(panel42); 6378 6379 JPanel panel43 = new JPanel(new FlowLayout()); 6380 panel43.add(new JLabel(Bundle.getMessage("MakeLabel", 6381 divergingBString))); 6382 panel43.add(d_3WaySignalHeadComboBox); 6383 d_3WaySignalHeadComboBox.setToolTipText(Bundle.getMessage("SignalHeadNameHint")); 6384 theContentPane.add(panel43); 6385 6386 JPanel panel44 = new JPanel(new FlowLayout()); 6387 panel44.add(new JLabel(" ")); 6388 panel44.add(setD3WayHead); 6389 setD3WayHead.setToolTipText(Bundle.getMessage("PlaceHeadHint")); 6390 panel44.add(new JLabel(" ")); 6391 panel44.add(setupD3WayLogic); 6392 setupD3WayLogic.setToolTipText(Bundle.getMessage("SetLogicHint")); 6393 theContentPane.add(panel44); 6394 theContentPane.add(new JSeparator(JSeparator.HORIZONTAL)); 6395 //buttons 6396 6397 JPanel panel6 = new JPanel(new FlowLayout()); 6398 panel6.add(change3WaySignalIcon = new JButton(Bundle.getMessage("ChangeSignalIcon"))); 6399 change3WaySignalIcon.addActionListener((ActionEvent e) -> signalFrame.setVisible(true)); 6400 change3WaySignalIcon.setToolTipText(Bundle.getMessage("ChangeSignalIconHint")); 6401 panel6.add(new JLabel(" ")); 6402 panel6.add(set3WaySignalsDone = new JButton(Bundle.getMessage("ButtonDone"))); 6403 set3WaySignalsDone.addActionListener(this::set3WaySignalsDonePressed); 6404 set3WaySignalsDone.setToolTipText(Bundle.getMessage("DoneHint", Bundle.getMessage("ButtonDone"))); 6405 6406 panel6.add(set3WaySignalsCancel = new JButton(Bundle.getMessage("ButtonCancel"))); 6407 set3WaySignalsCancel.addActionListener(this::set3WaySignalsCancelPressed); 6408 set3WaySignalsCancel.setToolTipText(Bundle.getMessage("CancelHint", Bundle.getMessage("ButtonCancel"))); 6409 theContentPane.add(panel6); 6410 6411 //make this button the default button (return or enter activates) 6412 JRootPane rootPane = SwingUtilities.getRootPane(set3WaySignalsDone); 6413 if (rootPane != null) { 6414 rootPane.setDefaultButton(set3WaySignalsDone); 6415 } 6416 6417 setSignalsAt3WayTurnoutFrame.addWindowListener(new WindowAdapter() { 6418 @Override 6419 public void windowClosing(WindowEvent e) { 6420 set3WaySignalsCancelPressed(null); 6421 } 6422 }); 6423 } 6424 setPlaceAllHeads.setSelected(false); 6425 setupAllLogic.setSelected(false); 6426 6427 turnoutAComboBox.setVisible(!setSignalsAt3WayTurnoutFromMenuFlag); 6428 turnoutBComboBox.setVisible(!setSignalsAt3WayTurnoutFromMenuFlag); 6429 if (setSignalsAt3WayTurnoutFromMenuFlag) { 6430 turnoutANameLabel.setText(Bundle.getMessage("MakeLabel", 6431 Bundle.getMessage("BeanNameTurnout") + " A") 6432 + turnoutAComboBox.getSelectedItemDisplayName()); 6433 turnoutBNameLabel.setText(Bundle.getMessage("MakeLabel", 6434 Bundle.getMessage("BeanNameTurnout") + " B") 6435 + turnoutBComboBox.getSelectedItemDisplayName()); 6436 getSaved3WaySignals(null); 6437 } else { 6438 turnoutANameLabel.setText(Bundle.getMessage("MakeLabel", 6439 Bundle.getMessage("TurnoutAName"))); 6440 turnoutBNameLabel.setText(Bundle.getMessage("MakeLabel", 6441 Bundle.getMessage("TurnoutBName"))); 6442 } 6443 6444 if (!setSignalsAt3WayTurnoutOpenFlag) { 6445 setSignalsAt3WayTurnoutFrame.setPreferredSize(null); 6446 setSignalsAt3WayTurnoutFrame.pack(); 6447 setSignalsAt3WayTurnoutOpenFlag = true; 6448 } 6449 setSignalsAt3WayTurnoutFrame.setVisible(true); 6450 } //setSignalsAt3WayTurnout 6451 6452 private void getSaved3WaySignals(ActionEvent a) { 6453 if (!get3WayTurnoutInformation()) { 6454 return; 6455 } 6456 a1_3WaySignalHeadComboBox.setSelectedItem(layoutTurnoutA.getSignalA1()); 6457 a2_3WaySignalHeadComboBox.setSelectedItem(layoutTurnoutA.getSignalA2()); 6458 a3_3WaySignalHeadComboBox.setSelectedItem(layoutTurnoutA.getSignalA3()); 6459 b_3WaySignalHeadComboBox.setSelectedItem(layoutTurnoutA.getSignalC1()); 6460 c_3WaySignalHeadComboBox.setSelectedItem(layoutTurnoutB.getSignalB1()); 6461 d_3WaySignalHeadComboBox.setSelectedItem(layoutTurnoutB.getSignalC1()); 6462 } 6463 6464 private void set3WaySignalsCancelPressed(ActionEvent a) { 6465 setSignalsAt3WayTurnoutOpenFlag = false; 6466 setSignalsAt3WayTurnoutFrame.setVisible(false); 6467 } 6468 6469 private boolean get3WayTurnoutInformation() { 6470 HitPointType type = HitPointType.NONE; 6471 Object connect = null; 6472 turnoutA = null; 6473 turnoutB = null; 6474 layoutTurnoutA = null; 6475 layoutTurnoutB = null; 6476 6477 String str = turnoutAComboBox.getSelectedItemDisplayName(); 6478 if ((str == null) || str.isEmpty()) { 6479 //turnout A not entered, test turnout B 6480 str = turnoutBComboBox.getSelectedItemDisplayName(); 6481 if ((str == null) || str.isEmpty()) { 6482 //no entries in turnout fields 6483 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 6484 Bundle.getMessage("SignalsError1"), 6485 Bundle.getMessage("ErrorTitle"), 6486 JmriJOptionPane.ERROR_MESSAGE); 6487 return false; 6488 } 6489 turnoutB = InstanceManager.turnoutManagerInstance().getTurnout(str); 6490 if (turnoutB == null) { 6491 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 6492 Bundle.getMessage("SignalsError2", 6493 new Object[]{str}), Bundle.getMessage("ErrorTitle"), 6494 JmriJOptionPane.ERROR_MESSAGE); 6495 return false; 6496 } 6497 String uname = turnoutB.getUserName(); 6498 if ((uname == null) || uname.isEmpty() 6499 || !uname.equals(str)) { 6500 turnoutBComboBox.setSelectedItem(turnoutB); 6501 } 6502 layoutTurnoutB = getLayoutTurnoutFromTurnout(turnoutB, false, str, setSignalsAt3WayTurnoutFrame); 6503 if (layoutTurnoutB == null) { 6504 return false; 6505 } 6506 //have turnout B and layout turnout B - look for turnout A 6507 connectorTrack = (TrackSegment) layoutTurnoutB.getConnectA(); 6508 if (connectorTrack == null) { 6509 //Inform user of error, and terminate 6510 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 6511 Bundle.getMessage("SignalsError19"), 6512 Bundle.getMessage("ErrorTitle"), 6513 JmriJOptionPane.ERROR_MESSAGE); 6514 return false; 6515 } 6516 type = connectorTrack.getType1(); 6517 connect = connectorTrack.getConnect1(); 6518 if (connect == layoutTurnoutB) { 6519 type = connectorTrack.getType2(); 6520 connect = connectorTrack.getConnect2(); 6521 } 6522 if ((type != HitPointType.TURNOUT_B) || (connect == null)) { 6523 //Not two turnouts connected as required by a single Track Segment 6524 //Inform user of error and terminate 6525 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 6526 Bundle.getMessage("SignalsError19"), 6527 Bundle.getMessage("ErrorTitle"), 6528 JmriJOptionPane.ERROR_MESSAGE); 6529 return false; 6530 } 6531 layoutTurnoutA = (LayoutTurnout) connect; 6532 turnoutA = layoutTurnoutA.getTurnout(); 6533 if (turnoutA == null) { 6534 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 6535 Bundle.getMessage("SignalsError19"), 6536 Bundle.getMessage("ErrorTitle"), 6537 JmriJOptionPane.ERROR_MESSAGE); 6538 return false; 6539 } 6540 turnoutAComboBox.setSelectedItem(turnoutA); 6541 } else { 6542 //something was entered in the turnout A field 6543 turnoutA = InstanceManager.turnoutManagerInstance().getTurnout(str); 6544 if (turnoutA == null) { 6545 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 6546 Bundle.getMessage("SignalsError2", 6547 new Object[]{str}), Bundle.getMessage("ErrorTitle"), 6548 JmriJOptionPane.ERROR_MESSAGE); 6549 return false; 6550 } 6551 String uname = turnoutA.getUserName(); 6552 if ((uname == null) || uname.isEmpty() 6553 || !uname.equals(str)) { 6554 turnoutAComboBox.setSelectedItem(turnoutA); 6555 } 6556 //have turnout A - get corresponding layoutTurnout 6557 layoutTurnoutA = getLayoutTurnoutFromTurnout(turnoutA, false, str, setSignalsAt3WayTurnoutFrame); 6558 if (layoutTurnoutA == null) { 6559 return false; 6560 } 6561 turnoutAComboBox.setSelectedItem(layoutTurnoutA.getTurnout()); 6562 //have turnout A and layout turnout A - was something entered for turnout B 6563 str = turnoutBComboBox.getSelectedItemDisplayName(); 6564 if ((str == null) || str.isEmpty()) { 6565 //no entry for turnout B 6566 connectorTrack = (TrackSegment) layoutTurnoutA.getConnectB(); 6567 if (connectorTrack == null) { 6568 //Inform user of error, and terminate 6569 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 6570 Bundle.getMessage("SignalsError19"), 6571 Bundle.getMessage("ErrorTitle"), 6572 JmriJOptionPane.ERROR_MESSAGE); 6573 return false; 6574 } 6575 type = connectorTrack.getType1(); 6576 connect = connectorTrack.getConnect1(); 6577 if (connect == layoutTurnoutA) { 6578 type = connectorTrack.getType2(); 6579 connect = connectorTrack.getConnect2(); 6580 } 6581 if ((type != HitPointType.TURNOUT_A) || (connect == null)) { 6582 // Not two turnouts connected with the throat of B connected to the continuing of A 6583 // by a single Track Segment. Inform user of error and terminate. 6584 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 6585 Bundle.getMessage("SignalsError19"), 6586 Bundle.getMessage("ErrorTitle"), 6587 JmriJOptionPane.ERROR_MESSAGE); 6588 return false; 6589 } 6590 layoutTurnoutB = (LayoutTurnout) connect; 6591 turnoutB = layoutTurnoutB.getTurnout(); 6592 if (turnoutB == null) { 6593 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 6594 Bundle.getMessage("SignalsError19"), 6595 Bundle.getMessage("ErrorTitle"), 6596 JmriJOptionPane.ERROR_MESSAGE); 6597 return false; 6598 } 6599 turnoutBComboBox.setSelectedItem(turnoutB); 6600 } else { 6601 //turnout B entered also 6602 turnoutB = InstanceManager.turnoutManagerInstance().getTurnout(str); 6603 if (turnoutB == null) { 6604 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 6605 Bundle.getMessage("SignalsError2", 6606 new Object[]{str}), Bundle.getMessage("ErrorTitle"), 6607 JmriJOptionPane.ERROR_MESSAGE); 6608 return false; 6609 } 6610 uname = turnoutB.getUserName(); 6611 if ((uname == null) || uname.isEmpty() 6612 || !uname.equals(str)) { 6613 turnoutBComboBox.setSelectedItem(turnoutB); 6614 } 6615 layoutTurnoutB = getLayoutTurnoutFromTurnout(turnoutB, false, str, setSignalsAt3WayTurnoutFrame); 6616 if (layoutTurnoutB == null) { 6617 return false; 6618 } 6619 turnoutBComboBox.setSelectedItem(layoutTurnoutB.getTurnout()); 6620 //check that layout turnout A and layout turnout B are connected as required 6621 if (layoutTurnoutA.getConnectB() != layoutTurnoutB.getConnectA()) { 6622 //Not two turnouts connected as required by a single Track Segment 6623 //Inform user of error and terminate 6624 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 6625 Bundle.getMessage("SignalsError19"), 6626 Bundle.getMessage("ErrorTitle"), 6627 JmriJOptionPane.ERROR_MESSAGE); 6628 return false; 6629 } 6630 connectorTrack = (TrackSegment) layoutTurnoutA.getConnectB(); 6631 } 6632 } 6633 return true; 6634 } //get3WayTurnoutInformation 6635 6636 private void set3WaySignalsDonePressed(ActionEvent a) { 6637 //process turnout names 6638 if (!get3WayTurnoutInformation()) { 6639 return; 6640 } 6641 //process signal head names 6642 if (!get3WaySignalHeadInformation()) { 6643 return; 6644 } 6645 //place signals as requested at turnout A 6646 String signalHeadName = a1_3WaySignalHeadComboBox.getSelectedItemDisplayName(); 6647 if (signalHeadName == null) { 6648 signalHeadName = ""; 6649 } 6650 if (setA13WayHead.isSelected()) { 6651 if (isHeadOnPanel(a13WayHead) 6652 && (a13WayHead != getHeadFromName(layoutTurnoutA.getSignalA1Name()))) { 6653 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 6654 Bundle.getMessage("SignalsError6", 6655 new Object[]{signalHeadName}), 6656 Bundle.getMessage("ErrorTitle"), 6657 JmriJOptionPane.ERROR_MESSAGE); 6658 return; 6659 } else { 6660 removeSignalHeadFromPanel(layoutTurnoutA.getSignalA1Name()); 6661 place3WayThroatContinuing(); 6662 removeAssignment(a13WayHead); 6663 layoutTurnoutA.setSignalA1Name(signalHeadName); 6664 needRedraw = true; 6665 } 6666 } else { 6667 LayoutTurnout.Geometry assigned = isHeadAssignedHere(a13WayHead, layoutTurnoutA); 6668 if (assigned == LayoutTurnout.Geometry.NONE) { 6669 if (isHeadOnPanel(a13WayHead) 6670 && isHeadAssignedAnywhere(a13WayHead)) { 6671 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 6672 Bundle.getMessage("SignalsError8", 6673 new Object[]{signalHeadName}), 6674 Bundle.getMessage("ErrorTitle"), 6675 JmriJOptionPane.ERROR_MESSAGE); 6676 return; 6677 } else { 6678 removeSignalHeadFromPanel(layoutTurnoutA.getSignalA1Name()); 6679 removeAssignment(a13WayHead); 6680 layoutTurnoutA.setSignalA1Name(signalHeadName); 6681 } 6682 //} else if (assigned != A1) { 6683 //need to figure out what to do in this case. 6684 } 6685 } 6686 6687 signalHeadName = a2_3WaySignalHeadComboBox.getSelectedItemDisplayName(); 6688 if (signalHeadName == null) { 6689 signalHeadName = ""; 6690 } 6691 if ((setA23WayHead.isSelected()) && (a23WayHead != null)) { 6692 if (isHeadOnPanel(a23WayHead) 6693 && (a23WayHead != getHeadFromName(layoutTurnoutA.getSignalA2Name()))) { 6694 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 6695 Bundle.getMessage("SignalsError6", 6696 new Object[]{signalHeadName}), 6697 Bundle.getMessage("ErrorTitle"), 6698 JmriJOptionPane.ERROR_MESSAGE); 6699 return; 6700 } else { 6701 removeSignalHeadFromPanel(layoutTurnoutA.getSignalA2Name()); 6702 place3WayThroatDivergingA(); 6703 removeAssignment(a23WayHead); 6704 layoutTurnoutA.setSignalA2Name(signalHeadName); 6705 needRedraw = true; 6706 } 6707 } else if (a23WayHead != null) { 6708 LayoutTurnout.Geometry assigned = isHeadAssignedHere(a23WayHead, layoutTurnoutA); 6709 if (assigned == LayoutTurnout.Geometry.NONE) { 6710 if (isHeadOnPanel(a23WayHead) 6711 && isHeadAssignedAnywhere(a23WayHead)) { 6712 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 6713 Bundle.getMessage("SignalsError8", 6714 new Object[]{signalHeadName}), 6715 Bundle.getMessage("ErrorTitle"), 6716 JmriJOptionPane.ERROR_MESSAGE); 6717 return; 6718 } else { 6719 removeSignalHeadFromPanel(layoutTurnoutA.getSignalA2Name()); 6720 removeAssignment(a23WayHead); 6721 layoutTurnoutA.setSignalA2Name(signalHeadName); 6722 } 6723 //} else if (assigned != A2) { 6724 //need to figure out what to do in this case. 6725 } 6726 } else { //a23WayHead is always null here 6727 removeSignalHeadFromPanel(layoutTurnoutA.getSignalA2Name()); 6728 layoutTurnoutA.setSignalA2Name(""); 6729 } 6730 6731 signalHeadName = a3_3WaySignalHeadComboBox.getSelectedItemDisplayName(); 6732 if (signalHeadName == null) { 6733 signalHeadName = ""; 6734 } 6735 if ((setA33WayHead.isSelected()) && (a33WayHead != null)) { 6736 if (isHeadOnPanel(a33WayHead) 6737 && (a33WayHead != getHeadFromName(layoutTurnoutA.getSignalA3Name()))) { 6738 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 6739 Bundle.getMessage("SignalsError6", 6740 new Object[]{signalHeadName}), 6741 Bundle.getMessage("ErrorTitle"), 6742 JmriJOptionPane.ERROR_MESSAGE); 6743 return; 6744 } else { 6745 removeSignalHeadFromPanel(layoutTurnoutA.getSignalA3Name()); 6746 place3WayThroatDivergingB(); 6747 removeAssignment(a33WayHead); 6748 layoutTurnoutA.setSignalA3Name(signalHeadName); 6749 needRedraw = true; 6750 } 6751 } else if (a33WayHead != null) { 6752 LayoutTurnout.Geometry assigned = isHeadAssignedHere(a33WayHead, layoutTurnoutA); 6753 if (assigned == LayoutTurnout.Geometry.NONE) { 6754 if (isHeadOnPanel(a33WayHead) 6755 && isHeadAssignedAnywhere(a33WayHead)) { 6756 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 6757 Bundle.getMessage("SignalsError8", 6758 new Object[]{signalHeadName}), 6759 Bundle.getMessage("ErrorTitle"), 6760 JmriJOptionPane.ERROR_MESSAGE); 6761 return; 6762 } else { 6763 removeSignalHeadFromPanel(layoutTurnoutA.getSignalA3Name()); 6764 removeAssignment(a33WayHead); 6765 layoutTurnoutA.setSignalA3Name(signalHeadName); 6766 } 6767 //} else if (assigned != A3) { 6768 //need to figure out what to do in this case. 6769 } 6770 } else { //a23WayHead is always null here 6771 removeSignalHeadFromPanel(layoutTurnoutA.getSignalA3Name()); 6772 layoutTurnoutA.setSignalA3Name(""); 6773 } 6774 6775 signalHeadName = b_3WaySignalHeadComboBox.getSelectedItemDisplayName(); 6776 if (signalHeadName == null) { 6777 signalHeadName = ""; 6778 } 6779 if (setB3WayHead.isSelected()) { 6780 if (isHeadOnPanel(b3WayHead) 6781 && (b3WayHead != getHeadFromName(layoutTurnoutA.getSignalC1Name()))) { 6782 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 6783 Bundle.getMessage("SignalsError6", 6784 new Object[]{signalHeadName}), 6785 Bundle.getMessage("ErrorTitle"), 6786 JmriJOptionPane.ERROR_MESSAGE); 6787 return; 6788 } else { 6789 removeSignalHeadFromPanel(layoutTurnoutA.getSignalC1Name()); 6790 place3WayDivergingA(); 6791 removeAssignment(b3WayHead); 6792 layoutTurnoutA.setSignalC1Name(signalHeadName); 6793 needRedraw = true; 6794 } 6795 } else { 6796 LayoutTurnout.Geometry assigned = isHeadAssignedHere(b3WayHead, layoutTurnoutA); 6797 if (assigned == LayoutTurnout.Geometry.NONE) { 6798 if (isHeadOnPanel(b3WayHead) 6799 && isHeadAssignedAnywhere(b3WayHead)) { 6800 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 6801 Bundle.getMessage("SignalsError8", 6802 new Object[]{signalHeadName}), 6803 Bundle.getMessage("ErrorTitle"), 6804 JmriJOptionPane.ERROR_MESSAGE); 6805 return; 6806 } else { 6807 removeSignalHeadFromPanel(layoutTurnoutA.getSignalC1Name()); 6808 removeAssignment(b3WayHead); 6809 layoutTurnoutA.setSignalC1Name(signalHeadName); 6810 } 6811 //} else if (assigned != A1) { 6812 //need to figure out what to do in this case. 6813 } 6814 } 6815 6816 //place signals as requested at Turnout C 6817 signalHeadName = c_3WaySignalHeadComboBox.getSelectedItemDisplayName(); 6818 if (signalHeadName == null) { 6819 signalHeadName = ""; 6820 } 6821 if (setC3WayHead.isSelected()) { 6822 if (isHeadOnPanel(c3WayHead) 6823 && (c3WayHead != getHeadFromName(layoutTurnoutB.getSignalB1Name()))) { 6824 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 6825 Bundle.getMessage("SignalsError6", 6826 new Object[]{signalHeadName}), 6827 Bundle.getMessage("ErrorTitle"), 6828 JmriJOptionPane.ERROR_MESSAGE); 6829 return; 6830 } else { 6831 removeSignalHeadFromPanel(layoutTurnoutB.getSignalB1Name()); 6832 place3WayContinuing(); 6833 removeAssignment(c3WayHead); 6834 layoutTurnoutB.setSignalB1Name(signalHeadName); 6835 needRedraw = true; 6836 } 6837 } else { 6838 LayoutTurnout.Geometry assigned = isHeadAssignedHere(c3WayHead, layoutTurnoutB); 6839 if (assigned == LayoutTurnout.Geometry.NONE) { 6840 if (isHeadOnPanel(c3WayHead) 6841 && isHeadAssignedAnywhere(c3WayHead)) { 6842 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 6843 Bundle.getMessage("SignalsError8", 6844 new Object[]{signalHeadName}), 6845 Bundle.getMessage("ErrorTitle"), 6846 JmriJOptionPane.ERROR_MESSAGE); 6847 return; 6848 } else { 6849 removeSignalHeadFromPanel(layoutTurnoutB.getSignalB1Name()); 6850 removeAssignment(c3WayHead); 6851 layoutTurnoutB.setSignalB1Name(signalHeadName); 6852 } 6853 //} else if (assigned != B1) { 6854 //need to figure out what to do in this case. 6855 } 6856 } 6857 6858 signalHeadName = d_3WaySignalHeadComboBox.getSelectedItemDisplayName(); 6859 if (signalHeadName == null) { 6860 signalHeadName = ""; 6861 } 6862 if (setD3WayHead.isSelected()) { 6863 if (isHeadOnPanel(d3WayHead) 6864 && (d3WayHead != getHeadFromName(layoutTurnoutB.getSignalC1Name()))) { 6865 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 6866 Bundle.getMessage("SignalsError6", 6867 new Object[]{signalHeadName}), 6868 Bundle.getMessage("ErrorTitle"), 6869 JmriJOptionPane.ERROR_MESSAGE); 6870 return; 6871 } else { 6872 removeSignalHeadFromPanel(layoutTurnoutB.getSignalC1Name()); 6873 place3WayDivergingB(); 6874 removeAssignment(d3WayHead); 6875 layoutTurnoutB.setSignalC1Name(signalHeadName); 6876 needRedraw = true; 6877 } 6878 } else { 6879 LayoutTurnout.Geometry assigned = isHeadAssignedHere(d3WayHead, layoutTurnoutB); 6880 if (assigned == LayoutTurnout.Geometry.NONE) { 6881 if (isHeadOnPanel(d3WayHead) 6882 && isHeadAssignedAnywhere(d3WayHead)) { 6883 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 6884 Bundle.getMessage("SignalsError8", 6885 new Object[]{signalHeadName}), 6886 Bundle.getMessage("ErrorTitle"), 6887 JmriJOptionPane.ERROR_MESSAGE); 6888 return; 6889 } else { 6890 removeSignalHeadFromPanel(layoutTurnoutB.getSignalC1Name()); 6891 removeAssignment(d3WayHead); 6892 layoutTurnoutB.setSignalC1Name(signalHeadName); 6893 } 6894 //} else if (assigned != C1) { 6895 //need to figure out what to do in this case. 6896 } 6897 } 6898 //setup Logic if requested and enough information is available 6899 if (setupA13WayLogic.isSelected()) { 6900 set3WayLogicThroatContinuing(); 6901 } 6902 if ((a23WayHead != null) && setupA23WayLogic.isSelected()) { 6903 set3WayLogicThroatDivergingA(); 6904 } 6905 if ((a33WayHead != null) && setupA33WayLogic.isSelected()) { 6906 set3WayLogicThroatDivergingB(); 6907 } 6908 if (setupB3WayLogic.isSelected()) { 6909 set3WayLogicDivergingA(); 6910 } 6911 if (setupC3WayLogic.isSelected()) { 6912 set3WayLogicContinuing(); 6913 } 6914 if (setupD3WayLogic.isSelected()) { 6915 set3WayLogicDivergingB(); 6916 } 6917 //link the two turnouts 6918 signalHeadName = turnoutBComboBox.getSelectedItemDisplayName(); 6919 if (signalHeadName == null) { 6920 signalHeadName = ""; 6921 } 6922 layoutTurnoutA.setLinkedTurnoutName(signalHeadName); 6923 layoutTurnoutA.setLinkType(LayoutTurnout.LinkType.FIRST_3_WAY); 6924 signalHeadName = turnoutAComboBox.getSelectedItemDisplayName(); 6925 if (signalHeadName == null) { 6926 signalHeadName = ""; 6927 } 6928 layoutTurnoutB.setLinkedTurnoutName(signalHeadName); 6929 layoutTurnoutB.setLinkType(LayoutTurnout.LinkType.SECOND_3_WAY); 6930 //finish up 6931 setSignalsAt3WayTurnoutOpenFlag = false; 6932 setSignalsAt3WayTurnoutFrame.setVisible(false); 6933 if (needRedraw) { 6934 layoutEditor.redrawPanel(); 6935 needRedraw = false; 6936 layoutEditor.setDirty(); 6937 } 6938 } //set3WaySignalsDonePressed 6939 6940 private boolean get3WaySignalHeadInformation() { 6941 a13WayHead = getSignalHeadFromEntry(a1_3WaySignalHeadComboBox, true, setSignalsAt3WayTurnoutFrame); 6942 if (a13WayHead == null) { 6943 return false; 6944 } 6945 a23WayHead = getSignalHeadFromEntry(a2_3WaySignalHeadComboBox, false, setSignalsAt3WayTurnoutFrame); 6946 a33WayHead = getSignalHeadFromEntry(a3_3WaySignalHeadComboBox, false, setSignalsAt3WayTurnoutFrame); 6947 if (((a23WayHead == null) && (a33WayHead != null)) || ((a33WayHead == null) 6948 && (a23WayHead != null))) { 6949 return false; 6950 } 6951 b3WayHead = getSignalHeadFromEntry(b_3WaySignalHeadComboBox, true, setSignalsAt3WayTurnoutFrame); 6952 if (b3WayHead == null) { 6953 return false; 6954 } 6955 c3WayHead = getSignalHeadFromEntry(c_3WaySignalHeadComboBox, true, setSignalsAt3WayTurnoutFrame); 6956 if (c3WayHead == null) { 6957 return false; 6958 } 6959 d3WayHead = getSignalHeadFromEntry(d_3WaySignalHeadComboBox, true, setSignalsAt3WayTurnoutFrame); 6960 if (d3WayHead == null) { 6961 return false; 6962 } 6963 return true; 6964 } 6965 6966 private void place3WayThroatContinuing() { 6967 if (testIcon == null) { 6968 testIcon = signalIconEditor.getIcon(0); 6969 } 6970 String signalHeadName = a1_3WaySignalHeadComboBox.getSelectedItemDisplayName(); 6971 if (signalHeadName == null) { 6972 signalHeadName = ""; 6973 } 6974 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 6975 6976 LayoutTurnoutView layoutTurnoutAView = layoutEditor.getLayoutTurnoutView(layoutTurnoutA); 6977 Point2D coordsA = layoutTurnoutAView.getCoordsA(); 6978 Point2D coordsCenter = layoutTurnoutAView.getCoordsCenter(); 6979 6980 double aDirDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsA, coordsCenter)); 6981 Point2D delta = new Point2D.Double(-shift, -shift); 6982 6983 delta = MathUtil.rotateDEG(delta, aDirDEG); 6984 Point2D where = MathUtil.add(coordsA, delta); 6985 setSignalHeadOnPanel(aDirDEG, signalHeadName, where); 6986 } 6987 6988 private void place3WayThroatDivergingA() { 6989 if (testIcon == null) { 6990 testIcon = signalIconEditor.getIcon(0); 6991 } 6992 String signalHeadName = a2_3WaySignalHeadComboBox.getSelectedItemDisplayName(); 6993 if (signalHeadName == null) { 6994 signalHeadName = ""; 6995 } 6996 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 6997 6998 LayoutTurnoutView layoutTurnoutAView = layoutEditor.getLayoutTurnoutView(layoutTurnoutA); 6999 Point2D coordsA = layoutTurnoutAView.getCoordsA(); 7000 Point2D coordsCenter = layoutTurnoutAView.getCoordsCenter(); 7001 7002 double aDirDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsA, coordsCenter)); 7003 Point2D delta = new Point2D.Double(+shift, -shift); 7004 7005 delta = MathUtil.rotateDEG(delta, aDirDEG); 7006 Point2D where = MathUtil.add(coordsA, delta); 7007 setSignalHeadOnPanel(aDirDEG, signalHeadName, where); 7008 } 7009 7010 private void place3WayThroatDivergingB() { 7011 if (testIcon == null) { 7012 testIcon = signalIconEditor.getIcon(0); 7013 } 7014 String signalHeadName = a3_3WaySignalHeadComboBox.getSelectedItemDisplayName(); 7015 if (signalHeadName == null) { 7016 signalHeadName = ""; 7017 } 7018 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 7019 7020 LayoutTurnoutView layoutTurnoutAView = layoutEditor.getLayoutTurnoutView(layoutTurnoutA); 7021 Point2D coordsA = layoutTurnoutAView.getCoordsA(); 7022 Point2D coordsCenter = layoutTurnoutAView.getCoordsCenter(); 7023 7024 double aDirDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsA, coordsCenter)); 7025 Point2D delta = new Point2D.Double(+3.0 * shift, -shift); 7026 7027 delta = MathUtil.rotateDEG(delta, aDirDEG); 7028 Point2D where = MathUtil.add(coordsA, delta); 7029 setSignalHeadOnPanel(aDirDEG, signalHeadName, where); 7030 } 7031 7032 private void place3WayDivergingA() { 7033 if (testIcon == null) { 7034 testIcon = signalIconEditor.getIcon(0); 7035 } 7036 String signalHeadName = b_3WaySignalHeadComboBox.getSelectedItemDisplayName(); 7037 if (signalHeadName == null) { 7038 signalHeadName = ""; 7039 } 7040 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 7041 7042 LayoutTurnoutView layoutTurnoutAView = layoutEditor.getLayoutTurnoutView(layoutTurnoutA); 7043 Point2D coordsB = layoutTurnoutAView.getCoordsB(); 7044 Point2D coordsC = layoutTurnoutAView.getCoordsC(); 7045 Point2D coordsCenter = layoutTurnoutAView.getCoordsCenter(); 7046 7047 double bDirDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsB, coordsCenter)); 7048 double cDirDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsC, coordsCenter)); 7049 double diffDirDEG = MathUtil.diffAngleDEG(cDirDEG, bDirDEG); 7050 double shiftX = shift; 7051 if (diffDirDEG >= 0.0) { 7052 shiftX += shift * Math.cos(Math.toRadians(diffDirDEG)); 7053 } 7054 Point2D delta = new Point2D.Double(shiftX, -shift); 7055 7056 delta = MathUtil.rotateDEG(delta, cDirDEG); 7057 Point2D where = MathUtil.add(coordsC, delta); 7058 setSignalHeadOnPanel(cDirDEG, signalHeadName, where); 7059 } 7060 7061 private void place3WayContinuing() { 7062 if (testIcon == null) { 7063 testIcon = signalIconEditor.getIcon(0); 7064 } 7065 String signalHeadName = c_3WaySignalHeadComboBox.getSelectedItemDisplayName(); 7066 if (signalHeadName == null) { 7067 signalHeadName = ""; 7068 } 7069 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 7070 7071 LayoutTurnoutView layoutTurnoutBView = layoutEditor.getLayoutTurnoutView(layoutTurnoutB); 7072 Point2D coordsB = layoutTurnoutBView.getCoordsB(); 7073 Point2D coordsC = layoutTurnoutBView.getCoordsC(); 7074 Point2D coordsCenter = layoutTurnoutBView.getCoordsCenter(); 7075 7076 double bDirDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsB, coordsCenter)); 7077 double cDirDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsC, coordsCenter)); 7078 double diffDirDEG = MathUtil.diffAngleDEG(cDirDEG, bDirDEG); 7079 double shiftX = shift; 7080 if (diffDirDEG >= 0.0) { 7081 shiftX += shift * Math.cos(Math.toRadians(diffDirDEG)); 7082 } 7083 Point2D delta = new Point2D.Double(shiftX, -shift); 7084 7085 delta = MathUtil.rotateDEG(delta, bDirDEG); 7086 Point2D where = MathUtil.add(coordsB, delta); 7087 setSignalHeadOnPanel(bDirDEG, signalHeadName, where); 7088 } 7089 7090 private void place3WayDivergingB() { 7091 if (testIcon == null) { 7092 testIcon = signalIconEditor.getIcon(0); 7093 } 7094 String signalHeadName = d_3WaySignalHeadComboBox.getSelectedItemDisplayName(); 7095 if (signalHeadName == null) { 7096 signalHeadName = ""; 7097 } 7098 double shift = Math.hypot(testIcon.getIconHeight(), testIcon.getIconWidth()) / 2.0; 7099 7100 LayoutTurnoutView layoutTurnoutBView = layoutEditor.getLayoutTurnoutView(layoutTurnoutB); 7101 Point2D coordsC = layoutTurnoutBView.getCoordsC(); 7102 Point2D coordsB = layoutTurnoutBView.getCoordsB(); 7103 Point2D coordsCenter = layoutTurnoutBView.getCoordsCenter(); 7104 7105 double bDirDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsB, coordsCenter)); 7106 double cDirDEG = MathUtil.wrap360(90.0 - MathUtil.computeAngleDEG(coordsC, coordsCenter)); 7107 double diffDirDEG = MathUtil.diffAngleDEG(cDirDEG, bDirDEG); 7108 double shiftX = shift; 7109 if (diffDirDEG >= 0.0) { 7110 shiftX += shift * Math.cos(Math.toRadians(diffDirDEG)); 7111 } 7112 Point2D delta = new Point2D.Double(shiftX, -shift); 7113 7114 delta = MathUtil.rotateDEG(delta, cDirDEG); 7115 Point2D where = MathUtil.add(coordsC, delta); 7116 setSignalHeadOnPanel(cDirDEG, signalHeadName, where); 7117 } 7118 7119 private void set3WayLogicThroatContinuing() { 7120 TrackSegment track = (TrackSegment) layoutTurnoutB.getConnectB(); 7121 if (track == null) { 7122 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 7123 Bundle.getMessage("InfoMessage7"), 7124 Bundle.getMessage("MessageTitle"), 7125 JmriJOptionPane.INFORMATION_MESSAGE); 7126 return; 7127 } 7128 LayoutBlock block = track.getLayoutBlock(); 7129 if (block == null) { 7130 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 7131 Bundle.getMessage("InfoMessage6"), 7132 Bundle.getMessage("MessageTitle"), 7133 JmriJOptionPane.INFORMATION_MESSAGE); 7134 return; 7135 } 7136 Sensor occupancy = block.getOccupancySensor(); 7137 if (occupancy == null) { 7138 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 7139 Bundle.getMessage("InfoMessage4", 7140 new Object[]{block.getUserName()}), 7141 Bundle.getMessage("MessageTitle"), 7142 JmriJOptionPane.INFORMATION_MESSAGE); 7143 return; 7144 } 7145 String signalHeadName = a1_3WaySignalHeadComboBox.getSelectedItemDisplayName(); 7146 if (signalHeadName == null) { 7147 signalHeadName = ""; 7148 } 7149 SignalHead nextHead = getNextSignalFromObject(track, layoutTurnoutB, 7150 signalHeadName, setSignalsAt3WayTurnoutFrame); 7151 if ((nextHead == null) && (!reachedEndBumper())) { 7152 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 7153 Bundle.getMessage("InfoMessage5", 7154 new Object[]{block.getUserName()}), 7155 Bundle.getMessage("MessageTitle"), 7156 JmriJOptionPane.INFORMATION_MESSAGE); 7157 return; 7158 } 7159 if (a23WayHead != null) { 7160 //set up logic for continuing head with 3 heads at throat 7161 if (!initializeBlockBossLogic(signalHeadName)) { 7162 return; 7163 } 7164 logic.setMode(BlockBossLogic.TRAILINGMAIN); 7165 logic.setTurnout(turnoutB.getDisplayName()); 7166 logic.setSensor1(occupancy.getDisplayName()); 7167 if (nextHead != null) { 7168 logic.setWatchedSignal1(nextHead.getDisplayName(), false); 7169 } 7170 if (auxSignal != null) { 7171 logic.setWatchedSignal1Alt(auxSignal.getDisplayName()); 7172 } 7173 String nearSensorName = setupNearLogix(layoutTurnoutA, true, a13WayHead); 7174 addNearSensorToLogic(nearSensorName); 7175 finalizeBlockBossLogic(); 7176 return; 7177 } 7178 //only one head at the throat 7179 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 7180 Bundle.getMessage("InfoMessage9"), 7181 Bundle.getMessage("MessageTitle"), 7182 JmriJOptionPane.INFORMATION_MESSAGE); 7183 return; 7184 } //set3WayLogicThroatContinuing 7185 7186 private void set3WayLogicThroatDivergingA() { 7187 TrackSegment track = (TrackSegment) layoutTurnoutA.getConnectC(); 7188 if (track == null) { 7189 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 7190 Bundle.getMessage("InfoMessage7"), 7191 Bundle.getMessage("MessageTitle"), 7192 JmriJOptionPane.INFORMATION_MESSAGE); 7193 return; 7194 } 7195 LayoutBlock block = track.getLayoutBlock(); 7196 if (block == null) { 7197 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 7198 Bundle.getMessage("InfoMessage6"), 7199 Bundle.getMessage("MessageTitle"), 7200 JmriJOptionPane.INFORMATION_MESSAGE); 7201 return; 7202 } 7203 Sensor occupancy = block.getOccupancySensor(); 7204 if (occupancy == null) { 7205 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 7206 Bundle.getMessage("InfoMessage4", 7207 new Object[]{block.getUserName()}), 7208 Bundle.getMessage("MessageTitle"), 7209 JmriJOptionPane.INFORMATION_MESSAGE); 7210 return; 7211 } 7212 String signalHeadName = a2_3WaySignalHeadComboBox.getSelectedItemDisplayName(); 7213 if (signalHeadName == null) { 7214 signalHeadName = ""; 7215 } 7216 SignalHead nextHead = getNextSignalFromObject(track, layoutTurnoutA, 7217 signalHeadName, setSignalsAt3WayTurnoutFrame); 7218 if ((nextHead == null) && (!reachedEndBumper())) { 7219 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 7220 Bundle.getMessage("InfoMessage5", 7221 new Object[]{block.getUserName()}), 7222 Bundle.getMessage("MessageTitle"), 7223 JmriJOptionPane.INFORMATION_MESSAGE); 7224 return; 7225 } 7226 if (!initializeBlockBossLogic(signalHeadName)) { 7227 return; 7228 } 7229 logic.setMode(BlockBossLogic.TRAILINGDIVERGING); 7230 logic.setTurnout(turnoutA.getDisplayName()); 7231 logic.setSensor1(occupancy.getDisplayName()); 7232 if (nextHead != null) { 7233 logic.setWatchedSignal1(nextHead.getDisplayName(), false); 7234 } 7235 if (auxSignal != null) { 7236 logic.setWatchedSignal1Alt(auxSignal.getDisplayName()); 7237 } 7238 if (!layoutTurnoutA.isMainlineC()) { 7239 logic.setLimitSpeed2(true); 7240 } 7241 finalizeBlockBossLogic(); 7242 } //set3WayLogicThroatDivergingA 7243 7244 private void set3WayLogicThroatDivergingB() { 7245 TrackSegment track = (TrackSegment) layoutTurnoutB.getConnectC(); 7246 if (track == null) { 7247 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 7248 Bundle.getMessage("InfoMessage7"), 7249 Bundle.getMessage("MessageTitle"), 7250 JmriJOptionPane.INFORMATION_MESSAGE); 7251 return; 7252 } 7253 LayoutBlock block = track.getLayoutBlock(); 7254 if (block == null) { 7255 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 7256 Bundle.getMessage("InfoMessage6"), 7257 Bundle.getMessage("MessageTitle"), 7258 JmriJOptionPane.INFORMATION_MESSAGE); 7259 return; 7260 } 7261 Sensor occupancy = block.getOccupancySensor(); 7262 if (occupancy == null) { 7263 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 7264 Bundle.getMessage("InfoMessage4", 7265 new Object[]{block.getUserName()}), 7266 Bundle.getMessage("MessageTitle"), 7267 JmriJOptionPane.INFORMATION_MESSAGE); 7268 return; 7269 } 7270 String signalHeadName = a3_3WaySignalHeadComboBox.getSelectedItemDisplayName(); 7271 if (signalHeadName == null) { 7272 signalHeadName = ""; 7273 } 7274 SignalHead nextHead = getNextSignalFromObject(track, layoutTurnoutB, 7275 signalHeadName, setSignalsAt3WayTurnoutFrame); 7276 if ((nextHead == null) && (!reachedEndBumper())) { 7277 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 7278 Bundle.getMessage("InfoMessage5", 7279 new Object[]{block.getUserName()}), 7280 Bundle.getMessage("MessageTitle"), 7281 JmriJOptionPane.INFORMATION_MESSAGE); 7282 return; 7283 } 7284 if (!initializeBlockBossLogic(signalHeadName)) { 7285 return; 7286 } 7287 logic.setMode(BlockBossLogic.TRAILINGDIVERGING); 7288 logic.setTurnout(turnoutB.getDisplayName()); 7289 logic.setSensor1(occupancy.getDisplayName()); 7290 if (nextHead != null) { 7291 logic.setWatchedSignal1(nextHead.getDisplayName(), false); 7292 } 7293 if (auxSignal != null) { 7294 logic.setWatchedSignal1Alt(auxSignal.getDisplayName()); 7295 } 7296 String nearSensorName = setupNearLogix(layoutTurnoutA, true, a33WayHead); 7297 addNearSensorToLogic(nearSensorName); 7298 if (!layoutTurnoutB.isMainlineC()) { 7299 logic.setLimitSpeed2(true); 7300 } 7301 finalizeBlockBossLogic(); 7302 } //set3WayLogicThroatDivergingB 7303 7304 private void set3WayLogicDivergingA() { 7305 TrackSegment track = (TrackSegment) layoutTurnoutA.getConnectA(); 7306 if (track == null) { 7307 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 7308 Bundle.getMessage("InfoMessage7"), 7309 Bundle.getMessage("MessageTitle"), 7310 JmriJOptionPane.INFORMATION_MESSAGE); 7311 return; 7312 } 7313 LayoutBlock block = track.getLayoutBlock(); 7314 if (block == null) { 7315 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 7316 Bundle.getMessage("InfoMessage6"), 7317 Bundle.getMessage("MessageTitle"), 7318 JmriJOptionPane.INFORMATION_MESSAGE); 7319 return; 7320 } 7321 Sensor occupancy = block.getOccupancySensor(); 7322 if (occupancy == null) { 7323 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 7324 Bundle.getMessage("InfoMessage4", 7325 new Object[]{block.getUserName()}), 7326 Bundle.getMessage("MessageTitle"), 7327 JmriJOptionPane.INFORMATION_MESSAGE); 7328 return; 7329 } 7330 String signalHeadName = b_3WaySignalHeadComboBox.getSelectedItemDisplayName(); 7331 if (signalHeadName == null) { 7332 signalHeadName = ""; 7333 } 7334 SignalHead nextHead = getNextSignalFromObject(track, layoutTurnoutA, 7335 signalHeadName, setSignalsAt3WayTurnoutFrame); 7336 if ((nextHead == null) && (!reachedEndBumper())) { 7337 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 7338 Bundle.getMessage("InfoMessage5", 7339 new Object[]{block.getUserName()}), 7340 Bundle.getMessage("MessageTitle"), 7341 JmriJOptionPane.INFORMATION_MESSAGE); 7342 return; 7343 } 7344 if (!initializeBlockBossLogic(signalHeadName)) { 7345 return; 7346 } 7347 logic.setMode(BlockBossLogic.TRAILINGDIVERGING); 7348 logic.setTurnout(turnoutA.getDisplayName()); 7349 logic.setSensor1(occupancy.getDisplayName()); 7350 if (nextHead != null) { 7351 logic.setWatchedSignal1(nextHead.getDisplayName(), false); 7352 } 7353 if (auxSignal != null) { 7354 logic.setWatchedSignal1Alt(auxSignal.getDisplayName()); 7355 } 7356 if (!layoutTurnoutA.isMainlineC()) { 7357 logic.setLimitSpeed2(true); 7358 } 7359 finalizeBlockBossLogic(); 7360 } //set3WayLogicDivergingA 7361 7362 private void set3WayLogicContinuing() { 7363 TrackSegment track = (TrackSegment) layoutTurnoutA.getConnectA(); 7364 if (track == null) { 7365 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 7366 Bundle.getMessage("InfoMessage7"), 7367 Bundle.getMessage("MessageTitle"), 7368 JmriJOptionPane.INFORMATION_MESSAGE); 7369 return; 7370 } 7371 LayoutBlock block = track.getLayoutBlock(); 7372 if (block == null) { 7373 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 7374 Bundle.getMessage("InfoMessage6"), 7375 Bundle.getMessage("MessageTitle"), 7376 JmriJOptionPane.INFORMATION_MESSAGE); 7377 return; 7378 } 7379 Sensor occupancy = block.getOccupancySensor(); 7380 if (occupancy == null) { 7381 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 7382 Bundle.getMessage("InfoMessage4", 7383 new Object[]{block.getUserName()}), 7384 Bundle.getMessage("MessageTitle"), 7385 JmriJOptionPane.INFORMATION_MESSAGE); 7386 return; 7387 } 7388 String signalHeadName = c_3WaySignalHeadComboBox.getSelectedItemDisplayName(); 7389 if (signalHeadName == null) { 7390 signalHeadName = ""; 7391 } 7392 SignalHead nextHead = getNextSignalFromObject(track, layoutTurnoutA, 7393 signalHeadName, setSignalsAt3WayTurnoutFrame); 7394 if ((nextHead == null) && (!reachedEndBumper())) { 7395 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 7396 Bundle.getMessage("InfoMessage5", 7397 new Object[]{block.getUserName()}), 7398 Bundle.getMessage("MessageTitle"), 7399 JmriJOptionPane.INFORMATION_MESSAGE); 7400 return; 7401 } 7402 if (!initializeBlockBossLogic(signalHeadName)) { 7403 return; 7404 } 7405 logic.setMode(BlockBossLogic.TRAILINGMAIN); 7406 logic.setTurnout(turnoutB.getDisplayName()); 7407 logic.setSensor1(occupancy.getDisplayName()); 7408 if (nextHead != null) { 7409 logic.setWatchedSignal1(nextHead.getDisplayName(), false); 7410 } 7411 if (auxSignal != null) { 7412 logic.setWatchedSignal1Alt(auxSignal.getDisplayName()); 7413 } 7414 String nearSensorName = setupNearLogix(layoutTurnoutA, true, c3WayHead); 7415 addNearSensorToLogic(nearSensorName); 7416 if (!layoutTurnoutB.isMainlineB()) { 7417 logic.setLimitSpeed2(true); 7418 } 7419 finalizeBlockBossLogic(); 7420 } //set3WayLogicContinuing 7421 7422 private void set3WayLogicDivergingB() { 7423 TrackSegment track = (TrackSegment) layoutTurnoutA.getConnectA(); 7424 if (track == null) { 7425 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 7426 Bundle.getMessage("InfoMessage7"), 7427 Bundle.getMessage("MessageTitle"), 7428 JmriJOptionPane.INFORMATION_MESSAGE); 7429 return; 7430 } 7431 LayoutBlock block = track.getLayoutBlock(); 7432 if (block == null) { 7433 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 7434 Bundle.getMessage("InfoMessage6"), 7435 Bundle.getMessage("MessageTitle"), 7436 JmriJOptionPane.INFORMATION_MESSAGE); 7437 return; 7438 } 7439 Sensor occupancy = block.getOccupancySensor(); 7440 if (occupancy == null) { 7441 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 7442 Bundle.getMessage("InfoMessage4", 7443 new Object[]{block.getUserName()}), 7444 Bundle.getMessage("MessageTitle"), 7445 JmriJOptionPane.INFORMATION_MESSAGE); 7446 return; 7447 } 7448 String signalHeadName = d_3WaySignalHeadComboBox.getSelectedItemDisplayName(); 7449 if (signalHeadName == null) { 7450 signalHeadName = ""; 7451 } 7452 SignalHead nextHead = getNextSignalFromObject(track, layoutTurnoutA, 7453 signalHeadName, setSignalsAt3WayTurnoutFrame); 7454 if ((nextHead == null) && (!reachedEndBumper())) { 7455 JmriJOptionPane.showMessageDialog(setSignalsAt3WayTurnoutFrame, 7456 Bundle.getMessage("InfoMessage5", 7457 new Object[]{block.getUserName()}), 7458 Bundle.getMessage("MessageTitle"), 7459 JmriJOptionPane.INFORMATION_MESSAGE); 7460 return; 7461 } 7462 if (!initializeBlockBossLogic(signalHeadName)) { 7463 return; 7464 } 7465 logic.setMode(BlockBossLogic.TRAILINGDIVERGING); 7466 logic.setTurnout(turnoutB.getDisplayName()); 7467 logic.setSensor1(occupancy.getDisplayName()); 7468 if (nextHead != null) { 7469 logic.setWatchedSignal1(nextHead.getDisplayName(), false); 7470 } 7471 if (auxSignal != null) { 7472 logic.setWatchedSignal1Alt(auxSignal.getDisplayName()); 7473 } 7474 String nearSensorName = setupNearLogix(layoutTurnoutA, true, d3WayHead); 7475 addNearSensorToLogic(nearSensorName); 7476 if (!layoutTurnoutB.isMainlineC()) { 7477 logic.setLimitSpeed2(true); 7478 } 7479 finalizeBlockBossLogic(); 7480 } //set3WayLogicDivergingB 7481 7482 /*===========================*\ 7483 |* setSensorsAtBlockBoundary *| 7484 \*===========================*/ 7485 // 7486 //The following is for placement of sensors and signal masts at points around the layout 7487 // 7488 //This section deals with assigning a sensor to a specific boundary point 7489 BeanDetails<Sensor> westBoundSensor; 7490 BeanDetails<Sensor> eastBoundSensor; 7491 7492 private JmriJFrame setSensorsAtBlockBoundaryFrame = null; 7493 private boolean setSensorsAtBlockBoundaryOpenFlag = false; 7494 private boolean setSensorsAtBlockBoundaryFromMenuFlag = false; 7495 7496 private JButton getAnchorSavedSensors = null; 7497 private JButton changeSensorAtBoundaryIcon = null; 7498 private JButton setSensorsAtBlockBoundaryDone = null; 7499 private JButton setSensorsAtBlockBoundaryCancel = null; 7500 7501 private JFrame sensorFrame = null; 7502 private MultiIconEditor sensorIconEditor = null; 7503 7504 JPanel sensorBlockPanel = new JPanel(new FlowLayout()); 7505 7506 public void setSensorsAtBlockBoundaryFromMenu(@Nonnull PositionablePoint p, 7507 @Nonnull MultiIconEditor theEditor, 7508 @Nonnull JFrame theFrame) { 7509 boundary = p; 7510 block1IDComboBox.setSelectedItem(boundary.getConnect1().getLayoutBlock().getBlock()); 7511 if (boundary.getConnect2() == null) { 7512 block2IDComboBox.setSelectedItem(boundary.getConnect1().getLayoutBlock().getBlock()); 7513 } else { 7514 block2IDComboBox.setSelectedItem(boundary.getConnect2().getLayoutBlock().getBlock()); 7515 } 7516 setSensorsAtBlockBoundaryFromMenuFlag = true; 7517 setSensorsAtBlockBoundary(theEditor, theFrame); 7518 setSensorsAtBlockBoundaryFromMenuFlag = false; 7519 } 7520 7521 //TODO: Add to Tools menu? 7522 public void setSensorsAtBlockBoundary(@Nonnull MultiIconEditor theEditor, 7523 @Nonnull JFrame theFrame) { 7524 sensorIconEditor = theEditor; 7525 sensorFrame = theFrame; 7526 7527 //Initialize if needed 7528 if (setSensorsAtBlockBoundaryFrame == null) { 7529 setSensorsAtBlockBoundaryOpenFlag = false; 7530 7531 westBoundSensor = new BeanDetails<>("Sensor", InstanceManager.sensorManagerInstance()); 7532 eastBoundSensor = new BeanDetails<>("Sensor", InstanceManager.sensorManagerInstance()); 7533 7534 setSensorsAtBlockBoundaryFrame = new JmriJFrame(Bundle.getMessage("SensorsAtBoundary"), false, true); 7535 oneFrameToRuleThemAll(setSensorsAtBlockBoundaryFrame); 7536 setSensorsAtBlockBoundaryFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 7537// setSensorsAtBlockBoundaryFrame.addHelpMenu("package.jmri.jmrit.display.SetSensorsAtBoundary", true); 7538 setSensorsAtBlockBoundaryFrame.setLocation(70, 30); 7539 Container theContentPane = setSensorsAtBlockBoundaryFrame.getContentPane(); 7540 theContentPane.setLayout(new BoxLayout(theContentPane, BoxLayout.Y_AXIS)); 7541 7542 JPanel header = new JPanel(); 7543 header.setLayout(new BoxLayout(header, BoxLayout.Y_AXIS)); 7544 7545 JPanel panel11 = new JPanel(new FlowLayout()); 7546 block1NameLabel = new JLabel(Bundle.getMessage("MakeLabel", 7547 Bundle.getMessage("BeanNameBlock") + " 1 - " 7548 + Bundle.getMessage("Name"))); 7549 panel11.add(block1NameLabel); 7550 7551 panel11.add(block1IDComboBox); 7552 block1IDComboBox.setToolTipText(Bundle.getMessage("SensorsBlockNameHint")); 7553 header.add(panel11); 7554 7555 JPanel panel12 = new JPanel(new FlowLayout()); 7556 block2NameLabel = new JLabel(Bundle.getMessage("MakeLabel", 7557 Bundle.getMessage("BeanNameBlock") + " 2 - " 7558 + Bundle.getMessage("Name"))); 7559 panel12.add(block2NameLabel); 7560 7561 panel12.add(block2IDComboBox); 7562 block2IDComboBox.setToolTipText(Bundle.getMessage("SensorsBlockNameHint")); 7563 header.add(panel12); 7564 7565 header.add(new JSeparator(JSeparator.HORIZONTAL)); 7566 theContentPane.add(header); 7567 7568 JPanel panel2 = new JPanel(new FlowLayout()); 7569 JLabel shTitle = new JLabel(Bundle.getMessage("Sensors")); 7570 panel2.add(shTitle); 7571 panel2.add(new JLabel(" ")); 7572 panel2.add(getAnchorSavedSensors = new JButton(Bundle.getMessage("GetSaved"))); 7573 getAnchorSavedSensors.addActionListener(this::getSavedAnchorSensors); 7574 getAnchorSavedSensors.setToolTipText(Bundle.getMessage("GetSavedHint")); 7575 theContentPane.add(panel2); 7576 7577 sensorBlockPanel.setLayout(new GridLayout(0, 1)); 7578 theContentPane.add(sensorBlockPanel); 7579 7580 theContentPane.add(new JSeparator(JSeparator.HORIZONTAL)); 7581 7582 JPanel panel6 = new JPanel(new FlowLayout()); 7583 panel6.add(changeSensorAtBoundaryIcon = new JButton(Bundle.getMessage("ChangeSensorIcon"))); 7584 changeSensorAtBoundaryIcon.addActionListener((ActionEvent e) -> sensorFrame.setVisible(true)); 7585 changeSensorAtBoundaryIcon.setToolTipText(Bundle.getMessage("ChangeSensorIconHint")); 7586 panel6.add(new JLabel(" ")); 7587 panel6.add(setSensorsAtBlockBoundaryDone = new JButton(Bundle.getMessage("ButtonDone"))); 7588 setSensorsAtBlockBoundaryDone.addActionListener(this::setSensorsAtBlockBoundaryDonePressed); 7589 setSensorsAtBlockBoundaryDone.setToolTipText(Bundle.getMessage("DoneHint", Bundle.getMessage("ButtonDone"))); 7590 7591 panel6.add(setSensorsAtBlockBoundaryCancel = new JButton(Bundle.getMessage("ButtonCancel"))); 7592 setSensorsAtBlockBoundaryCancel.addActionListener(this::setSensorsAtBlockBoundaryCancelPressed); 7593 setSensorsAtBlockBoundaryCancel.setToolTipText(Bundle.getMessage("CancelHint", Bundle.getMessage("ButtonCancel"))); 7594 theContentPane.add(panel6, BorderLayout.SOUTH); 7595 7596//make this button the default button (return or enter activates) 7597 JRootPane rootPane = SwingUtilities.getRootPane(setSensorsAtBlockBoundaryDone); 7598 if (rootPane != null) { 7599 rootPane.setDefaultButton(setSensorsAtBlockBoundaryDone); 7600 } 7601 7602 setSensorsAtBlockBoundaryFrame.addWindowListener(new WindowAdapter() { 7603 @Override 7604 public void windowClosing(WindowEvent e) { 7605 setSensorsAtBlockBoundaryCancelPressed(null); 7606 } 7607 }); 7608 } 7609 7610 sensorBlockPanel.removeAll(); 7611 7612 if (boundary.getType() != PositionablePoint.PointType.END_BUMPER) { 7613 eastBoundSensor.setBoundaryTitle(Bundle.getMessage("East/SouthBound")); 7614 if ((setSensorsAtBlockBoundaryFromMenuFlag) && (boundary.getType() == PositionablePoint.PointType.ANCHOR)) { 7615 if (isAtWestEndOfAnchor(boundary.getConnect1(), boundary)) { 7616 eastBoundSensor.setBoundaryLabelText(Bundle.getMessage("ProtectingBlock") + boundary.getConnect2().getLayoutBlock().getDisplayName()); 7617 } else { 7618 eastBoundSensor.setBoundaryLabelText(Bundle.getMessage("ProtectingBlock") + boundary.getConnect1().getLayoutBlock().getDisplayName()); 7619 } 7620 } 7621 eastBoundSensor.getDetailsPanel().setBackground(new Color(255, 255, 200)); 7622 sensorBlockPanel.add(eastBoundSensor.getDetailsPanel()); 7623 7624 westBoundSensor.setBoundaryTitle(Bundle.getMessage("West/NorthBound")); 7625 if (setSensorsAtBlockBoundaryFromMenuFlag) { 7626 if (isAtWestEndOfAnchor(boundary.getConnect1(), boundary)) { 7627 westBoundSensor.setBoundaryLabelText(Bundle.getMessage("ProtectingBlock") + boundary.getConnect1().getLayoutBlock().getDisplayName()); 7628 } else { 7629 westBoundSensor.setBoundaryLabelText(Bundle.getMessage("ProtectingBlock") + boundary.getConnect2().getLayoutBlock().getDisplayName()); 7630 } 7631 } 7632 westBoundSensor.getDetailsPanel().setBackground(new Color(200, 255, 255)); 7633 sensorBlockPanel.add(westBoundSensor.getDetailsPanel()); 7634 } else { 7635 if (setSensorsAtBlockBoundaryFromMenuFlag) { 7636 if (isAtWestEndOfAnchor(boundary.getConnect1(), boundary)) { 7637 eastBoundSensor.setBoundaryLabelText(Bundle.getMessage("ProtectingBlock") + boundary.getConnect1().getLayoutBlock().getDisplayName()); 7638 eastBoundSensor.getDetailsPanel().setBackground(new Color(200, 255, 255)); 7639 sensorBlockPanel.add(eastBoundSensor.getDetailsPanel()); 7640 } else { 7641 westBoundSensor.setBoundaryLabelText(Bundle.getMessage("ProtectingBlock") + boundary.getConnect1().getLayoutBlock().getDisplayName()); 7642 westBoundSensor.getDetailsPanel().setBackground(new Color(255, 255, 200)); 7643 sensorBlockPanel.add(westBoundSensor.getDetailsPanel()); 7644 } 7645 } 7646 } 7647 7648 block1IDComboBox.setVisible(!setSensorsAtBlockBoundaryFromMenuFlag); 7649 block2IDComboBox.setVisible(!setSensorsAtBlockBoundaryFromMenuFlag); 7650 7651 if (setSensorsAtBlockBoundaryFromMenuFlag) { 7652 block1NameLabel.setText(Bundle.getMessage("MakeLabel", 7653 Bundle.getMessage("BeanNameBlock") + " 1 " 7654 + Bundle.getMessage("Name")) 7655 + " " + boundary.getConnect1().getLayoutBlock().getId()); 7656 if (boundary.getConnect2() != null) { 7657 block2NameLabel.setText(Bundle.getMessage("MakeLabel", 7658 Bundle.getMessage("BeanNameBlock") + " 2 " 7659 + Bundle.getMessage("Name")) 7660 + " " + boundary.getConnect2().getLayoutBlock().getId()); 7661 } 7662 getSavedAnchorSensors(null); 7663 } else { 7664 block1NameLabel.setText(Bundle.getMessage("MakeLabel", 7665 Bundle.getMessage("Name") + " 1 " 7666 + Bundle.getMessage("Name"))); 7667 block2NameLabel.setText(Bundle.getMessage("MakeLabel", 7668 Bundle.getMessage("Name") + " 2 " 7669 + Bundle.getMessage("Name"))); 7670 } 7671 //boundary should never be null... however, just in case... 7672 boolean enable = ((boundary != null) && (boundary.getType() != PositionablePoint.PointType.END_BUMPER)); 7673 block2NameLabel.setVisible(enable); 7674 7675 if (!setSensorsAtBlockBoundaryOpenFlag) { 7676 setSensorsAtBlockBoundaryFrame.setPreferredSize(null); 7677 setSensorsAtBlockBoundaryFrame.pack(); 7678 setSensorsAtBlockBoundaryOpenFlag = true; 7679 } 7680 setSensorsAtBlockBoundaryFrame.setVisible(true); 7681 } //setSensorsAtBlockBoundary 7682 7683 /** 7684 * Returns the Sensor corresponding to an entry field in the specified 7685 * dialog. 7686 * <p> 7687 * This also takes care of UpperCase and trimming of leading and 7688 * trailing blanks. 7689 * If entry is required, and no entry is present, an error message is sent. 7690 * An error message also results if a sensor head with the 7691 * entered name is not found in the SensorTable. 7692 * @param sensorName sensor name. 7693 * @param requireEntry true if mandatory field, else false. 7694 * @param frame the main frame. 7695 * @return sensor, may be null. 7696 */ 7697 @CheckReturnValue 7698 public Sensor getSensorFromEntry(@CheckForNull String sensorName, 7699 boolean requireEntry, 7700 @Nonnull JmriJFrame frame) { 7701 if ((sensorName == null) || sensorName.isEmpty()) { 7702 if (requireEntry) { 7703 JmriJOptionPane.showMessageDialog(frame, Bundle.getMessage("SensorsError5"), 7704 Bundle.getMessage("ErrorTitle"), 7705 JmriJOptionPane.ERROR_MESSAGE); 7706 } 7707 return null; 7708 } 7709 Sensor head = InstanceManager.sensorManagerInstance().getSensor(sensorName); 7710 if (head == null) { 7711 JmriJOptionPane.showMessageDialog(frame, 7712 Bundle.getMessage("SensorsError4", 7713 new Object[]{sensorName}), Bundle.getMessage("ErrorTitle"), 7714 JmriJOptionPane.ERROR_MESSAGE); 7715 return null; 7716 } 7717 return (head); 7718 } 7719 7720 @CheckReturnValue 7721 public SensorIcon getSensorIcon(@Nonnull String sensorName) { 7722 SensorIcon l = new SensorIcon(new NamedIcon("resources/icons/smallschematics/tracksegments/circuit-error.gif", 7723 "resources/icons/smallschematics/tracksegments/circuit-error.gif"), layoutEditor); 7724 l.setIcon("SensorStateActive", sensorIconEditor.getIcon(0)); 7725 l.setIcon("SensorStateInactive", sensorIconEditor.getIcon(1)); 7726 l.setIcon("BeanStateInconsistent", sensorIconEditor.getIcon(2)); 7727 l.setIcon("BeanStateUnknown", sensorIconEditor.getIcon(3)); 7728 l.setSensor(sensorName); 7729 return l; 7730 } 7731 7732 /** 7733 * Returns true if the specified Sensor is assigned to an object on the 7734 * panel, regardless of whether an icon is displayed or not. With sensors we 7735 * NO LONGER (4.11.2) allow the same sensor to be allocated in both 7736 * directions. 7737 * 7738 * @param sensor The sensor to be checked. 7739 * @return true if the sensor is currently assigned someplace. 7740 */ 7741 public boolean isSensorAssignedAnywhere(@Nonnull Sensor sensor) { 7742 boolean result = false; 7743 7744 //check positionable points 7745 for (PositionablePoint po : layoutEditor.getPositionablePoints()) { 7746 if (po.getEastBoundSensor() == sensor) { 7747 result = true; 7748 break; 7749 } 7750 if (po.getWestBoundSensor() == sensor) { 7751 result = true; 7752 break; 7753 } 7754 } 7755 if (!result) { 7756 //check turnouts and slips 7757 for (LayoutTurnout to : layoutEditor.getLayoutTurnoutsAndSlips()) { 7758 if (whereIsSensorAssigned(sensor, to) != LayoutTurnout.Geometry.NONE) { 7759 result = true; 7760 break; 7761 } 7762 } 7763 } 7764 if (!result) { 7765 //check level crossings 7766 for (LevelXing x : layoutEditor.getLevelXings()) { 7767 if ((x.getSensorA() != null) && x.getSensorA() == sensor) { 7768 result = true; 7769 break; 7770 } 7771 if ((x.getSensorB() != null) && x.getSensorB() == sensor) { 7772 result = true; 7773 break; 7774 } 7775 if ((x.getSensorC() != null) && x.getSensorC() == sensor) { 7776 result = true; 7777 break; 7778 } 7779 if ((x.getSensorD() != null) && x.getSensorD() == sensor) { 7780 result = true; 7781 break; 7782 } 7783 } 7784 } 7785 7786 return result; 7787 } //isSensorAssignedAnywhere 7788 7789 private LayoutTurnout.Geometry whereIsSensorAssigned(Sensor sensor, LayoutTurnout lTurnout) { 7790 LayoutTurnout.Geometry result = LayoutTurnout.Geometry.NONE; 7791 7792 if (sensor != null && lTurnout != null) { 7793 String sName = sensor.getSystemName(); 7794 String uName = sensor.getUserName(); 7795 7796 String name = lTurnout.getSensorAName(); 7797 if (!name.isEmpty() && name.equals(uName) || name.equals(sName)) { 7798 return LayoutTurnout.Geometry.POINTA1; 7799 } 7800 name = lTurnout.getSensorBName(); 7801 if (!name.isEmpty() && name.equals(uName) || name.equals(sName)) { 7802 return LayoutTurnout.Geometry.POINTA2; 7803 } 7804 name = lTurnout.getSensorCName(); 7805 if (!name.isEmpty() && name.equals(uName) || name.equals(sName)) { 7806 return LayoutTurnout.Geometry.POINTA3; 7807 } 7808 name = lTurnout.getSensorDName(); 7809 if (!name.isEmpty() && name.equals(uName) || name.equals(sName)) { 7810 return LayoutTurnout.Geometry.POINTB1; 7811 } 7812 } 7813 return result; 7814 } 7815 7816 /** 7817 * Display an error dialog. 7818 * 7819 * @param sensor The sensor that is already assigned. 7820 */ 7821 void sensorAssignedElseWhere(@Nonnull Sensor sensor) { 7822 JmriJOptionPane.showMessageDialog(setSensorsAtBlockBoundaryFrame, 7823 Bundle.getMessage("SensorsError6", // NOI18N 7824 new Object[]{sensor.getDisplayName()}), 7825 Bundle.getMessage("ErrorTitle"), 7826 JmriJOptionPane.ERROR_MESSAGE); // NOI18N 7827 } 7828 7829 /** 7830 * Removes the assignment of the specified Sensor to either a turnout, a 7831 * positionable point, or a level crossing wherever it is assigned. Removes 7832 * any NX Pairs that use the sensor. 7833 * <p> 7834 * If the NX deletes fail due to Conditional references or user deny, the 7835 * assignment is not deleted. No additional notification is necessary since 7836 * they have already been notified or made a choice to not continue. 7837 * 7838 * @param sensor The sensor to be removed. 7839 * @return true if the sensor has been removed. 7840 */ 7841 public boolean removeSensorAssignment(@Nonnull Sensor sensor) { 7842 log.trace("Remove sensor assignment at block boundary for '{}'", sensor.getDisplayName()); // NOI18N 7843 if (!InstanceManager.getDefault(jmri.jmrit.entryexit.EntryExitPairs.class).deleteNxPair(sensor)) { 7844 log.trace("Removal of NX pairs for sensor '{}' failed", sensor.getDisplayName()); // NOI18N 7845 return false; 7846 } 7847 for (PositionablePoint po : layoutEditor.getPositionablePoints()) { 7848 if (po.getEastBoundSensor() == sensor) { 7849 po.setEastBoundSensor(null); 7850 } 7851 if (po.getWestBoundSensor() == sensor) { 7852 po.setWestBoundSensor(null); 7853 } 7854 } 7855 7856 for (LayoutTurnout to : layoutEditor.getLayoutTurnoutsAndSlips()) { 7857 if (to.getSensorA() == sensor) { 7858 to.setSensorA(null); 7859 } 7860 if (to.getSensorB() == sensor) { 7861 to.setSensorB(null); 7862 } 7863 if (to.getSensorC() == sensor) { 7864 to.setSensorC(null); 7865 } 7866 if (to.getSensorD() == sensor) { 7867 to.setSensorD(null); 7868 } 7869 } 7870 7871 for (LevelXing x : layoutEditor.getLevelXings()) { 7872 if (x.getSensorA() == sensor) { 7873 x.setSensorAName(null); 7874 } 7875 if (x.getSensorB() == sensor) { 7876 x.setSensorBName(null); 7877 } 7878 if (x.getSensorC() == sensor) { 7879 x.setSensorCName(null); 7880 } 7881 if (x.getSensorD() == sensor) { 7882 x.setSensorDName(null); 7883 } 7884 } 7885 7886 return true; 7887 } //removeSensorAssignment 7888 7889 /** 7890 * Removes the Sensor icon from the panel and from assignment to any 7891 * turnout, positionable point, or level crossing. 7892 * 7893 * @param sensor The sensor whose icon and references are to be removed. 7894 * @return true if the removal was successful. 7895 */ 7896 public boolean removeSensorFromPanel(@Nonnull Sensor sensor) { 7897 log.trace("Remove sensor icon and assignment for '{}'", sensor.getDisplayName()); // NOI18N 7898 if (!removeSensorAssignment(sensor)) { 7899 return false; 7900 } 7901 7902 SensorIcon h = null; 7903 int index = -1; 7904 for (int i = 0; (i < layoutEditor.getSensorList().size()) && (index == -1); i++) { 7905 h = layoutEditor.getSensorList().get(i); 7906 if (h.getSensor() == sensor) { 7907 index = i; 7908 } 7909 } 7910 if ((h != null) && (index != -1)) { 7911 layoutEditor.getSensorList().remove(index); 7912 h.remove(); 7913 h.dispose(); 7914 needRedraw = true; 7915 } 7916 return true; 7917 } 7918 7919 private void getSavedAnchorSensors(ActionEvent a) { 7920 if (!getSimpleBlockInformation()) { 7921 return; 7922 } 7923 eastBoundSensor.setTextField(boundary.getEastBoundSensorName()); 7924 westBoundSensor.setTextField(boundary.getWestBoundSensorName()); 7925 7926 if (boundary.getType() != PositionablePoint.PointType.END_BUMPER) { 7927 if (isAtWestEndOfAnchor(boundary.getConnect1(), boundary)) { 7928 eastBoundSensor.setBoundaryLabelText(Bundle.getMessage("ProtectingBlock") + boundary.getConnect2().getLayoutBlock().getDisplayName()); 7929 } else { 7930 eastBoundSensor.setBoundaryLabelText(Bundle.getMessage("ProtectingBlock") + boundary.getConnect1().getLayoutBlock().getDisplayName()); 7931 } 7932 if (isAtWestEndOfAnchor(boundary.getConnect1(), boundary)) { 7933 westBoundSensor.setBoundaryLabelText(Bundle.getMessage("ProtectingBlock") + boundary.getConnect1().getLayoutBlock().getDisplayName()); 7934 } else { 7935 westBoundSensor.setBoundaryLabelText(Bundle.getMessage("ProtectingBlock") + boundary.getConnect2().getLayoutBlock().getDisplayName()); 7936 } 7937 } else { 7938 if (isAtWestEndOfAnchor(boundary.getConnect1(), boundary)) { 7939 westBoundSensor.setBoundaryLabelText(Bundle.getMessage("EndOfBlock") + boundary.getConnect1().getLayoutBlock().getDisplayName()); 7940 } else { 7941 eastBoundSensor.setBoundaryLabelText(Bundle.getMessage("EndOfBlock") + boundary.getConnect1().getLayoutBlock().getDisplayName()); 7942 } 7943 } 7944 7945 setSensorsAtBlockBoundaryFrame.setPreferredSize(null); 7946 setSensorsAtBlockBoundaryFrame.pack(); 7947 } 7948 7949 private void setSensorsAtBlockBoundaryCancelPressed(ActionEvent a) { 7950 setSensorsAtBlockBoundaryOpenFlag = false; 7951 setSensorsAtBlockBoundaryFrame.setVisible(false); 7952 } 7953 7954 private void setSensorsAtBlockBoundaryDonePressed(ActionEvent a) { 7955 log.trace("setSensorsAtBlockBoundaryDonePressed"); // NOI18N 7956 if (!getSimpleBlockInformation()) { 7957 return; 7958 } 7959 7960 Sensor eastSensor = getSensorFromEntry(eastBoundSensor.getText(), false, setSensorsAtBlockBoundaryFrame); 7961 Sensor westSensor = getSensorFromEntry(westBoundSensor.getText(), false, setSensorsAtBlockBoundaryFrame); 7962 Sensor currEastSensor = InstanceManager.sensorManagerInstance().getSensor(boundary.getEastBoundSensorName()); 7963 Sensor currWestSensor = InstanceManager.sensorManagerInstance().getSensor(boundary.getWestBoundSensorName()); 7964 7965 if (log.isTraceEnabled()) { 7966 log.trace("current sensors: east = {}, west = {}", // NOI18N 7967 (currEastSensor == null) ? "- none- " : currEastSensor.getDisplayName(), // NOI18N 7968 (currWestSensor == null) ? "- none- " : currWestSensor.getDisplayName()); // NOI18N 7969 log.trace("new sensors: east = {}, west = {}", // NOI18N 7970 (eastSensor == null) ? "- none- " : eastSensor.getDisplayName(), // NOI18N 7971 (westSensor == null) ? "- none- " : westSensor.getDisplayName()); // NOI18N 7972 } 7973 7974 if (eastSensor == null) { 7975 if (currEastSensor != null && removeSensorFromPanel(currEastSensor)) { 7976 boundary.setEastBoundSensor(null); 7977 } 7978 } else if (eastBoundSensor != null) { 7979 setBoundarySensor(eastSensor, currEastSensor, eastBoundSensor, "East"); // NOI18N 7980 } 7981 7982 if (westSensor == null) { 7983 if (currWestSensor != null && removeSensorFromPanel(currWestSensor)) { 7984 boundary.setWestBoundSensor(null); 7985 } 7986 } else if (westBoundSensor != null) { 7987 setBoundarySensor(westSensor, currWestSensor, westBoundSensor, "West"); // NOI18N 7988 } 7989 7990 setSensorsAtBlockBoundaryOpenFlag = false; 7991 setSensorsAtBlockBoundaryFrame.setVisible(false); 7992 if (needRedraw) { 7993 layoutEditor.redrawPanel(); 7994 needRedraw = false; 7995 layoutEditor.setDirty(); 7996 } 7997 } 7998 7999 /** 8000 * Attached a sensor to the block boundary positional point. 8001 * 8002 * @since 4.11.2 8003 * @param newSensor The sensor that is being added. 8004 * @param currSensor The sensor that might already be there, otherwise null. 8005 * @param beanDetail The BeanDetails object that contains the supporting 8006 * data. 8007 * @param direction The direction, East or West. 8008 */ 8009 void setBoundarySensor(Sensor newSensor, Sensor currSensor, 8010 BeanDetails<Sensor> beanDetail, String direction) { 8011 if (currSensor == null) { 8012 if (!isSensorAssignedAnywhere(newSensor)) { 8013 log.trace("Add sensor '{}'", newSensor.getDisplayName()); // NOI18N 8014 if (direction.equals("West")) { // NOI18N 8015 boundary.setWestBoundSensor(beanDetail.getText()); 8016 } else { 8017 boundary.setEastBoundSensor(beanDetail.getText()); 8018 } 8019 if (beanDetail.addToPanel()) { 8020 log.trace("Add icon for sensor '{}'", newSensor.getDisplayName()); // NOI18N 8021 if (direction.equals("West")) { // NOI18N 8022 placeWestBoundIcon(getSensorIcon(beanDetail.getText()), 8023 beanDetail.isRightSelected(), 0.0); 8024 } else { 8025 placeEastBoundIcon(getSensorIcon(beanDetail.getText()), 8026 beanDetail.isRightSelected(), 0.0); 8027 } 8028 needRedraw = true; 8029 } 8030 } else { 8031 sensorAssignedElseWhere(newSensor); 8032 } 8033 } else if (currSensor == newSensor) { 8034 if (beanDetail.addToPanel()) { 8035 if (!isSensorOnPanel(newSensor)) { 8036 log.trace("Add icon for existing sensor '{}'", newSensor.getDisplayName()); // NOI18N 8037 if (direction.equals("West")) { // NOI18N 8038 placeWestBoundIcon(getSensorIcon(beanDetail.getText()), 8039 beanDetail.isRightSelected(), 0.0); 8040 } else { 8041 placeEastBoundIcon(getSensorIcon(beanDetail.getText()), 8042 beanDetail.isRightSelected(), 0.0); 8043 } 8044 needRedraw = true; 8045 } 8046 } 8047 } else { 8048 if (!isSensorAssignedAnywhere(newSensor)) { 8049 if (removeSensorFromPanel(currSensor)) { 8050 log.trace("Replace sensor '{}' with sensor '{}'", // NOI18N 8051 currSensor.getDisplayName(), newSensor.getDisplayName()); 8052 if (direction.equals("West")) { // NOI18N 8053 boundary.setWestBoundSensor(beanDetail.getText()); 8054 } else { 8055 boundary.setEastBoundSensor(beanDetail.getText()); 8056 } 8057 if (beanDetail.addToPanel()) { 8058 log.trace("Add icon for replacement sensor '{}'", // NOI18N 8059 newSensor.getDisplayName()); 8060 if (direction.equals("West")) { // NOI18N 8061 placeWestBoundIcon(getSensorIcon(beanDetail.getText()), 8062 beanDetail.isRightSelected(), 0.0); 8063 } else { 8064 placeEastBoundIcon(getSensorIcon(beanDetail.getText()), 8065 beanDetail.isRightSelected(), 0.0); 8066 } 8067 needRedraw = true; 8068 } 8069 } 8070 } else { 8071 sensorAssignedElseWhere(newSensor); 8072 } 8073 } 8074 } 8075 8076 public boolean isSensorOnPanel(@Nonnull Sensor sensor) { 8077 for (SensorIcon s : layoutEditor.getSensorList()) { 8078 if (s.getSensor() == sensor) { 8079 return true; 8080 } 8081 } 8082 return false; 8083 } 8084 8085 /*===============================*\ 8086 |* setSignalMastsAtBlockBoundary *| 8087 \*===============================*/ 8088 private JmriJFrame setSignalMastsAtBlockBoundaryFrame = null; 8089 private boolean setSignalMastsAtBlockBoundaryOpenFlag = false; 8090 private boolean setSignalMastsAtBlockBoundaryFromMenuFlag = false; 8091 8092 private JButton getAnchorSavedSignalMasts = null; 8093 private JButton setSignalMastsAtBlockBoundaryDone = null; 8094 private JButton setSignalMastsAtBlockBoundaryCancel = null; 8095 8096 BeanDetails<SignalMast> eastSignalMast; 8097 BeanDetails<SignalMast> westSignalMast; 8098 8099 JPanel signalMastBlockPanel = new JPanel(new FlowLayout()); 8100 8101 public void setSignalMastsAtBlockBoundaryFromMenu( 8102 @Nonnull PositionablePoint p) { 8103 boundary = p; 8104 block1IDComboBox.setSelectedItem(boundary.getConnect1().getLayoutBlock().getBlock()); 8105 if (boundary.getType() != PositionablePoint.PointType.END_BUMPER) { 8106 block2IDComboBox.setSelectedItem(boundary.getConnect2().getLayoutBlock().getBlock()); 8107 } else { 8108 block2IDComboBox.setSelectedItem(boundary.getConnect1().getLayoutBlock().getBlock()); 8109 } 8110 setSignalMastsAtBlockBoundaryFromMenuFlag = true; 8111 setSignalMastsAtBlockBoundary(); 8112 setSignalMastsAtBlockBoundaryFromMenuFlag = false; 8113 } 8114 8115 //TODO: Add to Tools menu? 8116 public void setSignalMastsAtBlockBoundary() { 8117 8118 //Initialize if needed 8119 if (setSignalMastsAtBlockBoundaryFrame == null) { 8120 setSignalMastsAtBlockBoundaryOpenFlag = false; 8121 8122 eastSignalMast = new BeanDetails<>("SignalMast", // NOI18N 8123 InstanceManager.getDefault(SignalMastManager.class)); 8124 westSignalMast = new BeanDetails<>("SignalMast", // NOI18N 8125 InstanceManager.getDefault(SignalMastManager.class)); 8126 8127 setSignalMastsAtBlockBoundaryFrame = new JmriJFrame(Bundle.getMessage("SignalMastsAtBoundary"), false, true); 8128 oneFrameToRuleThemAll(setSignalMastsAtBlockBoundaryFrame); 8129 setSignalMastsAtBlockBoundaryFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 8130 //setSignalMastsAtBlockBoundaryFrame.addHelpMenu("package.jmri.jmrit.display.SetSignalMastsAtBoundary", true); 8131 setSignalMastsAtBlockBoundaryFrame.setLocation(70, 30); 8132 Container theContentPane = setSignalMastsAtBlockBoundaryFrame.getContentPane(); 8133 theContentPane.setLayout(new BoxLayout(theContentPane, BoxLayout.Y_AXIS)); 8134 8135 JPanel header = new JPanel(); 8136 header.setLayout(new BoxLayout(header, BoxLayout.Y_AXIS)); 8137 8138 //Create the block 1 label and combo box 8139 JPanel panel11 = new JPanel(new FlowLayout()); 8140 block1NameLabel = new JLabel(Bundle.getMessage("MakeLabel", 8141 Bundle.getMessage("BeanNameBlock") + " 1 " 8142 + Bundle.getMessage("Name"))); 8143 panel11.add(block1NameLabel); 8144 panel11.add(block1IDComboBox); 8145 block1IDComboBox.setToolTipText(Bundle.getMessage("SignalMastsBlockNameHint")); 8146 header.add(panel11); 8147 8148 //Create the block 2 label and combo box, visibility will be controlled later 8149 block2NameLabel = new JLabel(Bundle.getMessage("MakeLabel", 8150 Bundle.getMessage("BeanNameBlock") + " 2 " 8151 + Bundle.getMessage("Name"))); 8152 block2IDComboBox.setToolTipText(Bundle.getMessage("SignalMastsBlockNameHint")); 8153 8154 JPanel panel12 = new JPanel(new FlowLayout()); 8155 panel12.add(block2NameLabel); 8156 panel12.add(block2IDComboBox); 8157 header.add(panel12); 8158 8159 header.add(new JSeparator(JSeparator.HORIZONTAL)); 8160 theContentPane.add(header); 8161 8162 JPanel panel2 = new JPanel(new FlowLayout()); 8163 JLabel shTitle = new JLabel(Bundle.getMessage("SignalMasts")); 8164 panel2.add(shTitle); 8165 panel2.add(new JLabel(" ")); 8166 panel2.add(getAnchorSavedSignalMasts = new JButton(Bundle.getMessage("GetSaved"))); 8167 getAnchorSavedSignalMasts.addActionListener(this::getSavedAnchorSignalMasts); 8168 getAnchorSavedSignalMasts.setToolTipText(Bundle.getMessage("GetSavedHint")); 8169 theContentPane.add(panel2); 8170 8171 signalMastBlockPanel.setLayout(new GridLayout(0, 1)); 8172 theContentPane.add(signalMastBlockPanel); 8173 8174 theContentPane.add(new JSeparator(JSeparator.HORIZONTAL)); 8175 8176 JPanel panel6 = new JPanel(new FlowLayout()); 8177 panel6.add(setSignalMastsAtBlockBoundaryDone = new JButton(Bundle.getMessage("ButtonDone"))); 8178 setSignalMastsAtBlockBoundaryDone.addActionListener(this::setSignalMastsAtBlockBoundaryDonePressed); 8179 setSignalMastsAtBlockBoundaryDone.setToolTipText(Bundle.getMessage("DoneHint", Bundle.getMessage("ButtonDone"))); 8180 8181 panel6.add(setSignalMastsAtBlockBoundaryCancel = new JButton(Bundle.getMessage("ButtonCancel"))); 8182 setSignalMastsAtBlockBoundaryCancel.addActionListener(this::setSignalMastsAtBlockBoundaryCancelPressed); 8183 setSignalMastsAtBlockBoundaryCancel.setToolTipText(Bundle.getMessage("CancelHint", Bundle.getMessage("ButtonCancel"))); 8184 theContentPane.add(panel6); 8185 8186 //make this button the default button (return or enter activates) 8187 JRootPane rootPane = SwingUtilities.getRootPane(setSignalMastsAtBlockBoundaryDone); 8188 if (rootPane != null) { 8189 rootPane.setDefaultButton(setSignalMastsAtBlockBoundaryDone); 8190 } 8191 8192 setSignalMastsAtBlockBoundaryFrame.addWindowListener(new WindowAdapter() { 8193 @Override 8194 public void windowClosing(WindowEvent e) { 8195 setSignalMastsAtBlockBoundaryCancelPressed(null); 8196 } 8197 }); 8198 } 8199 8200 eastSignalMast.getCombo().setExcludedItems(new HashSet<>()); 8201 westSignalMast.getCombo().setExcludedItems(new HashSet<>()); 8202 signalMastBlockPanel.removeAll(); 8203 8204 if (boundary.getType() != PositionablePoint.PointType.END_BUMPER) { //Anchor points and Edge Connectors 8205 eastSignalMast.setBoundaryTitle(Bundle.getMessage("East/SouthBound")); 8206 if (boundary.getType() == PositionablePoint.PointType.EDGE_CONNECTOR) { 8207 eastSignalMast.setBoundaryTitle(Bundle.getMessage("West/NorthBound")); 8208 } 8209 if (setSignalMastsAtBlockBoundaryFromMenuFlag) { 8210 if (isAtWestEndOfAnchor(boundary.getConnect1(), boundary)) { 8211 eastSignalMast.setBoundaryLabelText(Bundle.getMessage("ProtectingBlock") + boundary.getConnect2().getLayoutBlock().getDisplayName()); 8212 } else { 8213 eastSignalMast.setBoundaryLabelText(Bundle.getMessage("ProtectingBlock") + boundary.getConnect1().getLayoutBlock().getDisplayName()); 8214 } 8215 } 8216 eastSignalMast.getDetailsPanel().setBackground(new Color(255, 255, 200)); 8217 signalMastBlockPanel.add(eastSignalMast.getDetailsPanel()); 8218 8219 westSignalMast.setBoundaryTitle(Bundle.getMessage("West/NorthBound")); 8220 if (boundary.getType() == PositionablePoint.PointType.EDGE_CONNECTOR) { 8221 westSignalMast.setBoundaryTitle(Bundle.getMessage("East/SouthBound")); 8222 } 8223 if (setSignalMastsAtBlockBoundaryFromMenuFlag) { 8224 if (isAtWestEndOfAnchor(boundary.getConnect1(), boundary)) { 8225 westSignalMast.setBoundaryLabelText(Bundle.getMessage("ProtectingBlock") + boundary.getConnect1().getLayoutBlock().getDisplayName()); 8226 } else { 8227 westSignalMast.setBoundaryLabelText(Bundle.getMessage("ProtectingBlock") + boundary.getConnect2().getLayoutBlock().getDisplayName()); 8228 } 8229 } 8230 westSignalMast.getDetailsPanel().setBackground(new Color(200, 255, 255)); 8231 signalMastBlockPanel.add(westSignalMast.getDetailsPanel()); 8232 } else { //End Bumper 8233 if (setSignalMastsAtBlockBoundaryFromMenuFlag) { 8234 if (isAtWestEndOfAnchor(boundary.getConnect1(), boundary)) { 8235 eastSignalMast.setBoundaryLabelText(Bundle.getMessage("EndOfBlock") + boundary.getConnect1().getLayoutBlock().getDisplayName()); 8236 eastSignalMast.getDetailsPanel().setBackground(new Color(200, 255, 255)); 8237 signalMastBlockPanel.add(eastSignalMast.getDetailsPanel()); 8238 } else { 8239 westSignalMast.setBoundaryLabelText(Bundle.getMessage("EndOfBlock") + boundary.getConnect1().getLayoutBlock().getDisplayName()); 8240 westSignalMast.getDetailsPanel().setBackground(new Color(255, 255, 200)); 8241 signalMastBlockPanel.add(westSignalMast.getDetailsPanel()); 8242 } 8243 } 8244 } 8245 block1IDComboBox.setVisible(!setSignalMastsAtBlockBoundaryFromMenuFlag); 8246 block2IDComboBox.setVisible(!setSignalMastsAtBlockBoundaryFromMenuFlag); 8247 8248 if (setSignalMastsAtBlockBoundaryFromMenuFlag) { 8249 block1NameLabel.setText(Bundle.getMessage("MakeLabel", 8250 Bundle.getMessage("BeanNameBlock") + " 1 " 8251 + Bundle.getMessage("Name")) 8252 + " " + boundary.getConnect1().getLayoutBlock().getId()); 8253 if (boundary.getConnect2() != null) { 8254 block2NameLabel.setText(Bundle.getMessage("MakeLabel", 8255 Bundle.getMessage("BeanNameBlock") + " 2 " 8256 + Bundle.getMessage("Name")) 8257 + " " + boundary.getConnect2().getLayoutBlock().getId()); 8258 block2NameLabel.setVisible(true); 8259 } else { 8260 block2NameLabel.setVisible(false); 8261 } 8262 getSavedAnchorSignalMasts(null); 8263 } 8264 8265 if (!setSignalMastsAtBlockBoundaryOpenFlag) { 8266 setSignalMastsAtBlockBoundaryFrame.setPreferredSize(null); 8267 setSignalMastsAtBlockBoundaryFrame.pack(); 8268 setSignalMastsAtBlockBoundaryOpenFlag = true; 8269 } 8270 refreshSignalMastAtBoundaryComboBox(); 8271 setSignalMastsAtBlockBoundaryFrame.setVisible(true); 8272 } 8273 8274 /** 8275 * Returns the SignalMast corresponding to an entry field in the specified 8276 * dialog. This also takes care of UpperCase and trimming of leading and 8277 * trailing blanks. If entry is required, and no entry is present, and error 8278 * message is sent. An error message also results if a signalMast head with 8279 * the entered name is not found in the SignalMastTable. 8280 * @param signalMastName name of the signal mast. 8281 * @param requireEntry true if a required field, else false. 8282 * @param frame main frame. 8283 * @return signal mast, may be null. 8284 */ 8285 @CheckReturnValue 8286 public SignalMast getSignalMastFromEntry(@CheckForNull String signalMastName, 8287 boolean requireEntry, 8288 @Nonnull JmriJFrame frame) { 8289 if ((signalMastName == null) || signalMastName.isEmpty()) { 8290 if (requireEntry) { 8291 JmriJOptionPane.showMessageDialog(frame, Bundle.getMessage("SignalMastsError5"), 8292 Bundle.getMessage("ErrorTitle"), 8293 JmriJOptionPane.ERROR_MESSAGE); 8294 } 8295 return null; 8296 8297 } 8298 SignalMast head = InstanceManager.getDefault(SignalMastManager.class 8299 ).getSignalMast(signalMastName); 8300 if (head == null) { 8301 JmriJOptionPane.showMessageDialog(frame, 8302 Bundle.getMessage("SignalMastsError4", 8303 new Object[]{signalMastName}), Bundle.getMessage("ErrorTitle"), 8304 JmriJOptionPane.ERROR_MESSAGE); 8305 return null; 8306 } 8307 return (head); 8308 } 8309 8310 /** 8311 * Returns true if the specified SignalMast is assigned to an object on the 8312 * panel, regardless of whether an icon is displayed or not. 8313 * @param signalMast the signal mast to query. 8314 * @return true if associated with panel, else false. 8315 */ 8316 public boolean isSignalMastAssignedAnywhere(@Nonnull SignalMast signalMast) { 8317 boolean result = false; 8318 for (PositionablePoint po : layoutEditor.getPositionablePoints()) { 8319 if ((po.getEastBoundSignalMast() != null) && po.getEastBoundSignalMast() == signalMast) { 8320 result = true; 8321 break; 8322 } 8323 if ((po.getWestBoundSignalMast() != null) && po.getWestBoundSignalMast() == signalMast) { 8324 result = true; 8325 break; 8326 } 8327 } 8328 8329 if (!result) { 8330 for (LayoutTurnout to : layoutEditor.getLayoutTurnoutsAndSlips()) { 8331 if ((to.getSignalAMast() != null) && to.getSignalAMast() == signalMast) { 8332 result = true; 8333 break; 8334 } 8335 if ((to.getSignalBMast() != null) && to.getSignalBMast() == signalMast) { 8336 result = true; 8337 break; 8338 } 8339 if ((to.getSignalCMast() != null) && to.getSignalCMast() == signalMast) { 8340 result = true; 8341 break; 8342 } 8343 if ((to.getSignalDMast() != null) && to.getSignalDMast() == signalMast) { 8344 result = true; 8345 break; 8346 } 8347 } 8348 } 8349 8350 if (!result) { 8351 for (LevelXing x : layoutEditor.getLevelXings()) { 8352 if ((x.getSignalAMast() != null) && x.getSignalAMast() == signalMast) { 8353 result = true; 8354 break; 8355 } 8356 if ((x.getSignalBMast() != null) && x.getSignalBMast() == signalMast) { 8357 result = true; 8358 break; 8359 } 8360 if ((x.getSignalCMast() != null) && x.getSignalCMast() == signalMast) { 8361 result = true; 8362 break; 8363 } 8364 if ((x.getSignalDMast() != null) && x.getSignalDMast() == signalMast) { 8365 result = true; 8366 break; 8367 } 8368 } 8369 } 8370 return result; 8371 } 8372 8373 /** 8374 * Removes the assignment of the specified SignalMast to either a turnout, a 8375 * positionable point, or a level crossing wherever it is assigned. 8376 * @param signalMast the signal mast to remove. 8377 */ 8378 public void removeSignalMastAssignment(@CheckForNull SignalMast signalMast) { 8379 if (signalMast == null) { 8380 return; 8381 } 8382 8383 for (PositionablePoint po : layoutEditor.getPositionablePoints()) { 8384 if ((po.getEastBoundSignalMast() != null) && po.getEastBoundSignalMast() == signalMast) { 8385 po.setEastBoundSignalMast(null); 8386 } 8387 if ((po.getWestBoundSignalMast() != null) && po.getWestBoundSignalMast() == signalMast) { 8388 po.setWestBoundSignalMast(null); 8389 } 8390 } 8391 for (LayoutTurnout to : layoutEditor.getLayoutTurnoutsAndSlips()) { 8392 if ((to.getSignalAMast() != null) && to.getSignalAMast() == signalMast) { 8393 to.setSignalAMast(null); 8394 } 8395 if ((to.getSignalBMast() != null) && to.getSignalBMast() == signalMast) { 8396 to.setSignalBMast(null); 8397 } 8398 if ((to.getSignalCMast() != null) && to.getSignalCMast() == signalMast) { 8399 to.setSignalCMast(null); 8400 } 8401 if ((to.getSignalDMast() != null) && to.getSignalDMast() == signalMast) { 8402 to.setSignalDMast(null); 8403 } 8404 } 8405 8406 for (LevelXing x : layoutEditor.getLevelXings()) { 8407 if ((x.getSignalAMast() != null) && x.getSignalAMast() == signalMast) { 8408 x.setSignalAMast(null); 8409 } 8410 8411 if ((x.getSignalBMast() != null) && x.getSignalBMast() == signalMast) { 8412 x.setSignalBMast(null); 8413 } 8414 8415 if ((x.getSignalCMast() != null) && x.getSignalCMast() == signalMast) { 8416 x.setSignalCMast(null); 8417 } 8418 8419 if ((x.getSignalDMast() != null) && x.getSignalDMast() == signalMast) { 8420 x.setSignalDMast(null); 8421 } 8422 } 8423 } 8424 8425 /** 8426 * Removes the SignalMast with the specified name from the panel and from 8427 * assignment to any turnout, positionable point, or level crossing. 8428 * @param signalMast the signal mast to remove. 8429 */ 8430 public void removeSignalMastFromPanel(@Nonnull SignalMast signalMast) { 8431 removeSignalMastAssignment(signalMast); 8432 SignalMastIcon h = null; 8433 int index = -1; 8434 for (int i = 0; (i < layoutEditor.getSignalMastList().size()) && (index == -1); i++) { 8435 h = layoutEditor.getSignalMastList().get(i); 8436 if ((h != null) && (h.getSignalMast() == signalMast)) { 8437 index = i; 8438 } 8439 } 8440 if ((h != null) && (index != -1)) { 8441 layoutEditor.getSignalMastList().remove(index); 8442 h.remove(); 8443 h.dispose(); 8444 needRedraw = true; 8445 } 8446 } 8447 8448 private void getSavedAnchorSignalMasts(ActionEvent a) { 8449 if (!getSimpleBlockInformation()) { 8450 return; 8451 } 8452 8453 eastSignalMast.setTextField(boundary.getEastBoundSignalMastName()); 8454 westSignalMast.setTextField(boundary.getWestBoundSignalMastName()); 8455 8456 if (boundary.getType() != PositionablePoint.PointType.END_BUMPER) { 8457 if (isAtWestEndOfAnchor(boundary.getConnect1(), boundary)) { 8458 eastSignalMast.setBoundaryLabelText(Bundle.getMessage("ProtectingBlock") + boundary.getConnect2().getLayoutBlock().getDisplayName()); 8459 } else { 8460 eastSignalMast.setBoundaryLabelText(Bundle.getMessage("ProtectingBlock") + boundary.getConnect1().getLayoutBlock().getDisplayName()); 8461 } 8462 if (isAtWestEndOfAnchor(boundary.getConnect1(), boundary)) { 8463 westSignalMast.setBoundaryLabelText(Bundle.getMessage("ProtectingBlock") + boundary.getConnect1().getLayoutBlock().getDisplayName()); 8464 } else { 8465 westSignalMast.setBoundaryLabelText(Bundle.getMessage("ProtectingBlock") + boundary.getConnect2().getLayoutBlock().getDisplayName()); 8466 } 8467 } else { 8468 if (isAtWestEndOfAnchor(boundary.getConnect1(), boundary)) { 8469 westSignalMast.setBoundaryLabelText(Bundle.getMessage("EndOfBlock") + boundary.getConnect1().getLayoutBlock().getDisplayName()); 8470 } else { 8471 eastSignalMast.setBoundaryLabelText(Bundle.getMessage("EndOfBlock") + boundary.getConnect1().getLayoutBlock().getDisplayName()); 8472 } 8473 } 8474 setSignalMastsAtBlockBoundaryFrame.setPreferredSize(null); 8475 setSignalMastsAtBlockBoundaryFrame.pack(); 8476 } 8477 8478 private void setSignalMastsAtBlockBoundaryCancelPressed(ActionEvent a) { 8479 setSignalMastsAtBlockBoundaryOpenFlag = false; 8480 setSignalMastsAtBlockBoundaryFrame.setVisible(false); 8481 } 8482 8483 void refreshSignalMastAtBoundaryComboBox() { 8484 createListUsedSignalMasts(); 8485 usedMasts.remove(eastSignalMast.getBean()); 8486 usedMasts.remove(westSignalMast.getBean()); 8487 eastSignalMast.getCombo().setExcludedItems(usedMasts); 8488 westSignalMast.getCombo().setExcludedItems(usedMasts); 8489 } 8490 8491 private void setSignalMastsAtBlockBoundaryDonePressed(ActionEvent a) { 8492 if (!getSimpleBlockInformation()) { 8493 return; 8494 } 8495 8496 SignalMast oldBlock1SignalMast = boundary.getEastBoundSignalMast(); 8497 SignalMast block1BoundSignalMast = getSignalMastFromEntry(eastSignalMast.getText(), false, setSignalMastsAtBlockBoundaryFrame); 8498 8499 if (block1BoundSignalMast == null) { 8500 if (InstanceManager.getDefault(LayoutBlockManager.class).isAdvancedRoutingEnabled() 8501 && InstanceManager.getDefault(SignalMastLogicManager.class).isSignalMastUsed(oldBlock1SignalMast)) { 8502 SignallingGuiTools.removeSignalMastLogic(setSignalMastsAtBlockBoundaryFrame, oldBlock1SignalMast); 8503 } 8504 8505 removeSignalMastFromPanel(boundary.getEastBoundSignalMast()); 8506 removeSignalMastAssignment(boundary.getEastBoundSignalMast()); 8507 boundary.setEastBoundSignalMast(""); 8508 } 8509 8510 SignalMast oldBlock2SignalMast = boundary.getWestBoundSignalMast(); 8511 SignalMast block2BoundSignalMast = getSignalMastFromEntry(westSignalMast.getText(), false, setSignalMastsAtBlockBoundaryFrame); 8512 8513 if (block2BoundSignalMast == null) { 8514 if (InstanceManager.getDefault(LayoutBlockManager.class 8515 ).isAdvancedRoutingEnabled() && InstanceManager.getDefault(SignalMastLogicManager.class 8516 ).isSignalMastUsed(oldBlock2SignalMast)) { 8517 SignallingGuiTools.removeSignalMastLogic(setSignalMastsAtBlockBoundaryFrame, oldBlock2SignalMast); 8518 } 8519 8520 removeSignalMastFromPanel(boundary.getWestBoundSignalMast()); 8521 removeSignalMastAssignment(boundary.getWestBoundSignalMast()); 8522 boundary.setWestBoundSignalMast(""); 8523 } 8524 if (block2BoundSignalMast != null && block1BoundSignalMast != null) { 8525 if (block1BoundSignalMast == block2BoundSignalMast) { 8526 JmriJOptionPane.showMessageDialog(setSignalMastsAtBlockBoundaryFrame, 8527 Bundle.getMessage("SignalMastsError14"), 8528 Bundle.getMessage("ErrorTitle"), 8529 JmriJOptionPane.ERROR_MESSAGE); 8530 return; 8531 } 8532 if (oldBlock1SignalMast == block2BoundSignalMast && oldBlock2SignalMast == block1BoundSignalMast) { 8533 //We are going for a swap! 8534 //Need to remove old items first 8535 removeSignalMastFromPanel(boundary.getWestBoundSignalMast()); 8536 removeSignalMastFromPanel(boundary.getEastBoundSignalMast()); 8537 removeSignalMastAssignment(block1BoundSignalMast); 8538 removeSignalMastAssignment(block2BoundSignalMast); 8539 //Then place new ones 8540 SignalMastIcon l; 8541 if (eastSignalMast.addToPanel()) { 8542 l = new SignalMastIcon(layoutEditor); 8543 l.setSignalMast(eastSignalMast.getText()); 8544 placeEastBoundIcon(l, eastSignalMast.isRightSelected(), 0); 8545 } 8546 if (westSignalMast.addToPanel()) { 8547 l = new SignalMastIcon(layoutEditor); 8548 l.setSignalMast(westSignalMast.getText()); 8549 placeWestBoundIcon(l, westSignalMast.isRightSelected(), 0); 8550 } 8551 boundary.setEastBoundSignalMast(eastSignalMast.getText()); 8552 boundary.setWestBoundSignalMast(westSignalMast.getText()); 8553 //Then sort out the logic 8554 8555 if (InstanceManager.getDefault(LayoutBlockManager.class 8556 ).isAdvancedRoutingEnabled()) { 8557 SignallingGuiTools.swapSignalMastLogic(setSignalMastsAtBlockBoundaryFrame, block1BoundSignalMast, block2BoundSignalMast); 8558 } 8559 needRedraw = true; 8560 } 8561 } 8562 if (!needRedraw) { 8563 if (block1BoundSignalMast != null) { 8564 if (eastSignalMast.addToPanel()) { 8565 if (isSignalMastAssignedAnywhere(block1BoundSignalMast) 8566 && (block1BoundSignalMast != oldBlock1SignalMast)) { 8567 JmriJOptionPane.showMessageDialog(setSignalMastsAtBlockBoundaryFrame, 8568 Bundle.getMessage("SignalMastsError6", 8569 new Object[]{eastSignalMast.getText()}), 8570 Bundle.getMessage("ErrorTitle"), 8571 JmriJOptionPane.ERROR_MESSAGE); 8572 return; 8573 } else { 8574 removeSignalMastFromPanel(boundary.getEastBoundSignalMast()); 8575 SignalMastIcon l = new SignalMastIcon(layoutEditor); 8576 l.setSignalMast(eastSignalMast.getText()); 8577 placeEastBoundIcon(l, eastSignalMast.isRightSelected(), 0); 8578 removeSignalMastAssignment(block1BoundSignalMast); 8579 boundary.setEastBoundSignalMast(eastSignalMast.getText()); 8580 needRedraw = true; 8581 } 8582 } else if ((block1BoundSignalMast != boundary.getEastBoundSignalMast()) 8583 && (block1BoundSignalMast != boundary.getWestBoundSignalMast())) { 8584 if (isSignalMastOnPanel(block1BoundSignalMast)) { 8585 JmriJOptionPane.showMessageDialog(setSignalMastsAtBlockBoundaryFrame, 8586 Bundle.getMessage("SignalMastsError13", 8587 new Object[]{eastSignalMast.getText()}), 8588 Bundle.getMessage("ErrorTitle"), 8589 JmriJOptionPane.ERROR_MESSAGE); 8590 return; 8591 } else { 8592 removeSignalMastFromPanel(boundary.getEastBoundSignalMast()); 8593 removeSignalMastAssignment(block1BoundSignalMast); 8594 boundary.setEastBoundSignalMast(eastSignalMast.getText()); 8595 } 8596 } 8597 } 8598 if (block2BoundSignalMast != null) { 8599 if (westSignalMast.addToPanel()) { 8600 if (isSignalMastAssignedAnywhere(block2BoundSignalMast) 8601 && (block2BoundSignalMast != oldBlock2SignalMast)) { 8602 JmriJOptionPane.showMessageDialog(setSignalMastsAtBlockBoundaryFrame, 8603 Bundle.getMessage("SignalMastsError6", 8604 new Object[]{westSignalMast.getText()}), 8605 Bundle.getMessage("ErrorTitle"), 8606 JmriJOptionPane.ERROR_MESSAGE); 8607 return; 8608 } else /*(oldBlock2SignalMast!=block2BoundSignalMast)*/ { 8609 removeSignalMastFromPanel(boundary.getWestBoundSignalMast()); 8610 SignalMastIcon l = new SignalMastIcon(layoutEditor); 8611 l.setSignalMast(westSignalMast.getText()); 8612 placeWestBoundIcon(l, westSignalMast.isRightSelected(), 0); 8613 removeSignalMastAssignment(block2BoundSignalMast); 8614 boundary.setWestBoundSignalMast(westSignalMast.getText()); 8615 needRedraw = true; 8616 } 8617 } else if ((block2BoundSignalMast != boundary.getEastBoundSignalMast()) 8618 && (block2BoundSignalMast != oldBlock2SignalMast)) { 8619 if (isSignalMastAssignedAnywhere(block2BoundSignalMast)) { 8620 //Need to do this better, so that the signalMast can be on panel multiple times but only alocated to one anchor at a time 8621 JmriJOptionPane.showMessageDialog(setSignalMastsAtBlockBoundaryFrame, 8622 Bundle.getMessage("SignalMastsError13", 8623 new Object[]{westSignalMast.getText()}), 8624 Bundle.getMessage("ErrorTitle"), 8625 JmriJOptionPane.ERROR_MESSAGE); 8626 return; 8627 } else { 8628 removeSignalMastFromPanel(boundary.getWestBoundSignalMast()); 8629 removeSignalMastAssignment(block2BoundSignalMast); 8630 boundary.setWestBoundSignalMast(westSignalMast.getText()); 8631 8632 } 8633 } 8634 } 8635 8636 //If advanced routing is enabled and then this indicates that we are using this for discovering the signalmast logic paths. 8637 if (InstanceManager.getDefault(LayoutBlockManager.class 8638 ).isAdvancedRoutingEnabled() 8639 && (block1BoundSignalMast != null 8640 || block2BoundSignalMast != null)) { 8641 if ((oldBlock1SignalMast != null) && (block2BoundSignalMast != null)) { 8642 updateBoundaryBasedSignalMastLogic( 8643 oldBlock1SignalMast, oldBlock2SignalMast, 8644 block1BoundSignalMast, block2BoundSignalMast); 8645 8646 } 8647 } 8648 } 8649 setSignalMastsAtBlockBoundaryOpenFlag = false; 8650 setSignalMastsAtBlockBoundaryFrame.setVisible(false); 8651 if (needRedraw) { 8652 layoutEditor.redrawPanel(); 8653 needRedraw = false; 8654 layoutEditor.setDirty(); 8655 } 8656 } 8657 8658 public void updateBoundaryBasedSignalMastLogic( 8659 @Nonnull SignalMast oldBlock1SignalMast, 8660 @Nonnull SignalMast oldBlock2SignalMast, 8661 @Nonnull SignalMast block1BoundSignalMast, 8662 @Nonnull SignalMast block2BoundSignalMast) { 8663 SignalMastLogicManager smlm = InstanceManager.getDefault(SignalMastLogicManager.class 8664 ); 8665 boolean old1Used = smlm.isSignalMastUsed(oldBlock1SignalMast); 8666 boolean old2Used = smlm.isSignalMastUsed(oldBlock2SignalMast); 8667 //Just check that the old ones are used in logics somewhere. 8668 if (old1Used || old2Used) { 8669 boolean new1Used = smlm.isSignalMastUsed(block1BoundSignalMast); 8670 boolean new2Used = smlm.isSignalMastUsed(block2BoundSignalMast); 8671 if (new1Used || new2Used) { 8672 if ((new1Used) && (block1BoundSignalMast != oldBlock1SignalMast)) { 8673 SignallingGuiTools.removeAlreadyAssignedSignalMastLogic(setSignalMastsAtBlockBoundaryFrame, block1BoundSignalMast); 8674 } 8675 if ((new2Used) && (block2BoundSignalMast != oldBlock2SignalMast)) { 8676 SignallingGuiTools.removeAlreadyAssignedSignalMastLogic(setSignalMastsAtBlockBoundaryFrame, block2BoundSignalMast); 8677 } 8678 } 8679 if (block1BoundSignalMast != null) { 8680 if (oldBlock2SignalMast != null && old2Used 8681 && oldBlock2SignalMast == block1BoundSignalMast) { 8682 SignallingGuiTools.updateSignalMastLogic(setSignalMastsAtBlockBoundaryFrame, oldBlock2SignalMast, block1BoundSignalMast); 8683 } 8684 8685 if (oldBlock1SignalMast != null && old1Used 8686 && oldBlock1SignalMast != block1BoundSignalMast) { 8687 8688 SignallingGuiTools.updateSignalMastLogic(setSignalMastsAtBlockBoundaryFrame, oldBlock1SignalMast, block1BoundSignalMast); 8689 } 8690 } 8691 if (block2BoundSignalMast != null) { 8692 if (old1Used && oldBlock1SignalMast == block2BoundSignalMast) { 8693 8694 SignallingGuiTools.updateSignalMastLogic(setSignalMastsAtBlockBoundaryFrame, oldBlock1SignalMast, block2BoundSignalMast); 8695 } 8696 if (old2Used && oldBlock2SignalMast != block2BoundSignalMast) { 8697 SignallingGuiTools.updateSignalMastLogic(setSignalMastsAtBlockBoundaryFrame, oldBlock2SignalMast, block2BoundSignalMast); 8698 } 8699 } 8700 } 8701 } 8702 8703 public void setIconOnPanel(@Nonnull PositionableIcon l, 8704 int rotation, @Nonnull Point p) { 8705 setIconOnPanel(l, rotation, (int) p.getX(), (int) p.getY()); 8706 } 8707 8708 public void setIconOnPanel(@Nonnull PositionableIcon l, 8709 int rotation, int xLoc, int yLoc) { 8710 l.setLocation(xLoc, yLoc); 8711 if (rotation > 0) { 8712 l.rotate(rotation); 8713 } 8714 if (l instanceof SignalMastIcon) { 8715 layoutEditor.putSignalMast((SignalMastIcon) l); 8716 } else if (l instanceof SensorIcon) { 8717 layoutEditor.putSensor((SensorIcon) l); 8718 } else if (l instanceof SignalHeadIcon) { 8719 layoutEditor.putSignal((SignalHeadIcon) l); 8720 } 8721 } 8722 8723 private void placeEastBoundIcon(PositionableIcon icon, boolean isRightSide, double fromPoint) { 8724 8725 Point2D p = layoutEditor.getLayoutTrackView(boundary).getCoordsCenter(); 8726 8727 //Track segment is used to determine the alignment, 8728 // therefore this is opposite to the block that we are protecting 8729 8730 //For edge connectors we need to do two things: 8731 // - change the dir value as east and west are swapped 8732 // - and as we have only one track segment on any one layout editor 8733 // so we determine where the track segment would end if we did a mirror image 8734 // so that the calculations for angled segments is correct 8735 8736 TrackSegment t = boundary.getConnect2(); 8737 boolean dir = true; 8738 boolean shouldUseConnect2 = true; 8739 8740 if (boundary.getType() == PositionablePoint.PointType.END_BUMPER) { 8741 t = boundary.getConnect1(); 8742 } else{ 8743 if (isAtWestEndOfAnchor(boundary.getConnect1(), boundary)) { 8744 t = boundary.getConnect1(); 8745 } 8746 } 8747 8748 if (boundary.getType() == PositionablePoint.PointType.EDGE_CONNECTOR) { 8749 t = boundary.getConnect1(); //have to use connect1 as there is only one track segment attached to edge connector 8750 if (isAtWestEndOfAnchor(boundary.getConnect1(), boundary)) { 8751 shouldUseConnect2 = false; 8752 } 8753 } 8754 8755 Point2D pt2; 8756 if (t.getConnect1() == boundary){ 8757 pt2 = layoutEditor.getCoords(t.getConnect2(), t.getType2()); 8758 } else { 8759 pt2 = layoutEditor.getCoords(t.getConnect1(), t.getType1()); 8760 } 8761 8762 if (boundary.getType() == PositionablePoint.PointType.EDGE_CONNECTOR) { 8763 Point2D p3 = (Point2D) pt2.clone(); 8764 if (shouldUseConnect2) { 8765 //use a point opposite pt2 (= p + p- pt2 using vector addition) 8766 double px = p.getX(); 8767 double py = p.getY(); 8768 double p2x = pt2.getX(); 8769 double p2y = pt2.getY(); 8770 double p3x = px + px - p2x; 8771 double p3y = py + py - p2y; 8772 p3.setLocation(p3x, p3y); 8773 } 8774 dir = false; //east and west are swapped with edge connectors 8775 setIconOnPanel(t, icon, dir, p, p3, isRightSide, fromPoint); 8776 } else{ 8777 setIconOnPanel(t, icon, dir, p, pt2, isRightSide, fromPoint); 8778 } 8779 8780 } 8781 8782 private void placeWestBoundIcon(PositionableIcon icon, boolean isRightSide, double fromPoint) { 8783 8784 Point2D p = layoutEditor.getLayoutTrackView(boundary).getCoordsCenter(); 8785 8786 //Track segment is used to determine the alignment, 8787 // therefore this is opposite to the block that we are protecting 8788 8789 //For edge connectors we need to do two things: 8790 // - change the dir value as east and west are swapped 8791 // - and as we have only one track segment on any one layout editor 8792 // so we determine where the track segment would end if we did a mirror image 8793 // so that the calculations for angled segments is correct 8794 8795 TrackSegment t = boundary.getConnect1(); 8796 boolean dir = false; 8797 boolean shouldUseConnect2 = false; 8798 if (boundary.getType() != PositionablePoint.PointType.END_BUMPER) { 8799 if (isAtWestEndOfAnchor(boundary.getConnect1(), boundary)) { 8800 t = boundary.getConnect2(); 8801 } 8802 } 8803 8804 if (boundary.getType() == PositionablePoint.PointType.EDGE_CONNECTOR) { 8805 t = boundary.getConnect1(); //have to use connect1 as there is only one track segment attached to edge connector 8806 if (isAtWestEndOfAnchor(boundary.getConnect1(), boundary)) { 8807 shouldUseConnect2 = true; 8808 } 8809 } 8810 8811 Point2D pt2; 8812 if (t.getConnect1() == boundary) { 8813 pt2 = layoutEditor.getCoords(t.getConnect2(), t.getType2()); 8814 } else { 8815 pt2 = layoutEditor.getCoords(t.getConnect1(), t.getType1()); 8816 } 8817 8818 if (boundary.getType() == PositionablePoint.PointType.EDGE_CONNECTOR) { 8819 Point2D p3 = (Point2D) pt2.clone(); 8820 if (shouldUseConnect2) { 8821 //use a point opposite pt2 (= p + p - pt2 using vector addition) 8822 double px = p.getX(); 8823 double py = p.getY(); 8824 double p2x = pt2.getX(); 8825 double p2y = pt2.getY(); 8826 double p3x = px + px - p2x; 8827 double p3y = py + py - p2y; 8828 p3.setLocation(p3x, p3y); 8829 } 8830 dir = true; //east and west are swapped with edge connectors 8831 setIconOnPanel(t, icon, dir, p, p3, isRightSide, fromPoint); 8832 } else{ 8833 setIconOnPanel(t, icon, dir, p, pt2, isRightSide, fromPoint); 8834 } 8835 } 8836 8837 private void setIconOnPanel(@Nonnull TrackSegment t, 8838 @Nonnull PositionableIcon l, 8839 boolean isEastBound, @Nonnull Point2D pt1, @Nonnull Point2D pt2, 8840 boolean isRightSide, double fromPoint) { 8841 double pt1x = pt1.getX(), pt1y = pt1.getY(); 8842 double pt2x = pt2.getX(), pt2y = pt2.getY(); 8843 8844 int triX = (int) Math.round(pt2x - pt1x); 8845 int triY = (int) Math.round(pt2y - pt1y); 8846 8847 if (log.isDebugEnabled()) { 8848 log.debug("X {} Y {}", triX, triY); 8849 } 8850 Point loc; 8851 if (triX == 0 || triX == 360) { 8852 //In a vertical Straight Line 8853 if (isEastBound) { 8854 log.debug("In a vertical straightline facing South"); 8855 loc = northToSouth(pt1, l, isRightSide, fromPoint); 8856 } else { 8857 log.debug("In a vertical striaghtline facing North"); 8858 loc = southToNorth(pt1, l, isRightSide, fromPoint); 8859 } 8860 } else if (triY == 0 || triY == 360) { 8861 //In a Horizontal Straight Line 8862 if (isEastBound) { 8863 log.debug("In a Horizontal striaghtline facing east"); 8864 loc = westToEast(pt1, l, isRightSide, fromPoint); 8865 } else { 8866 log.debug("In a Horizontal striaghtline facing west"); 8867 loc = eastToWest(pt1, l, isRightSide, fromPoint); 8868 } 8869 } else { 8870 //Compute arc's chord 8871 double a = pt2x - pt1x; 8872 double o = pt2y - pt1y; 8873 double radius = Math.hypot(a, o); //chord equates to radius of circle 8874 8875 double pt1xa = pt1x + radius; 8876 double a1 = pt2x - pt1xa; 8877 double o1 = pt2y - pt1y; 8878 double chord = Math.hypot(a1, o1); 8879 double rsq = Math.pow(radius, 2); 8880 8881 double radAngleFromDatum = Math.acos((rsq + rsq - Math.pow(chord, 2)) / (2 * rsq)); 8882 if (log.isDebugEnabled()) { 8883 log.debug("radius {} Chord {}", radius, chord); 8884 log.debug("Angle from datum line {}", Math.toDegrees(radAngleFromDatum)); 8885 } 8886 8887 int rotateDEG = ((int) Math.toDegrees(radAngleFromDatum)); 8888 8889 if (log.isDebugEnabled()) { 8890 double tanx = o / a; 8891 double angletanRAD = Math.atan2(o, a); 8892 log.debug("{} = atan2({}, {}) ({})", Math.toDegrees(angletanRAD), o, a, tanx); 8893 } 8894 8895 int oldHeight = l.maxHeight(); 8896 int oldWidth = l.maxWidth(); 8897 8898 //pt1 is always our boundary point 8899 //East side 8900 if (pt2x > pt1x) { 8901 //East Sides 8902 if (pt2y > pt1y) { 8903 //"South East Corner" 8904 rotateDEG = rotateDEG + 270; //Correct for SM111, sm101, sm121, SM80 8905 l.rotate(rotateDEG); 8906 loc = southEastToNorthWest(pt1, l, oldWidth, oldHeight, rotateDEG, isRightSide, fromPoint); 8907 } else { 8908 //"North East corner" //correct for sm110, sm70, sm131 8909 rotateDEG = 270 - rotateDEG; 8910 l.rotate(rotateDEG); 8911 loc = northEastToSouthWest(pt1, l, oldWidth, oldHeight, rotateDEG, isRightSide, fromPoint); 8912 } 8913 8914 } else { 8915 //West Side 8916 if (pt2y > pt1y) { 8917 //South West //WORKING FOR SM141, sm130, SM71 8918 l.rotate(rotateDEG - 90); 8919 //South West 8920 loc = southWestToNorthEast(pt1, l, oldWidth, oldHeight, rotateDEG, isRightSide, fromPoint); 8921 } else { 8922 //North West //Working FOR SM140, SM81, sm120 8923 rotateDEG = (180 - rotateDEG) + 90; 8924 l.rotate(rotateDEG); 8925 loc = northWestToSouthEast(pt1, l, oldWidth, oldHeight, rotateDEG, isRightSide, fromPoint); 8926 } 8927 } 8928 } 8929 setIconOnPanel(l, 0, loc); 8930 } 8931 8932 Point southToNorth(Point2D p, PositionableIcon l, boolean right, double fromPoint) { 8933 int offsetx = 0; 8934 int offsety = (int) (p.getY() + offSetFromPoint + fromPoint); 8935 if (right) { 8936 offsetx = (int) p.getX() + offSetFromPoint; 8937 } else { 8938 offsetx = (int) p.getX() - offSetFromPoint - l.maxWidth(); 8939 } 8940 return new Point(offsetx, offsety); 8941 } 8942 8943 Point northToSouth(Point2D p, PositionableIcon l, boolean right, double fromPoint) { 8944 l.rotate(180); 8945 int offsetx = 0; 8946 int offsety = (int) (p.getY() - (offSetFromPoint + fromPoint) - l.maxHeight()); 8947 if (right) { 8948 offsetx = (int) p.getX() - offSetFromPoint - l.maxWidth(); 8949 } else { 8950 offsetx = (int) p.getX() + offSetFromPoint; 8951 } 8952 return new Point(offsetx, offsety); 8953 } 8954 8955 Point westToEast(Point2D p, PositionableIcon l, boolean right, double fromPoint) { 8956 l.rotate(90); 8957 int offsetx = (int) (p.getX() - (l.maxWidth() + (offSetFromPoint + fromPoint - 1))); 8958 int offsety = 0; 8959 if (right) { 8960 offsety = (int) p.getY() + (offSetFromPoint - 1); 8961 } else { 8962 offsety = (int) p.getY() - (offSetFromPoint) - l.maxHeight(); 8963 } 8964 return new Point(offsetx, offsety); 8965 } 8966 8967 Point eastToWest(Point2D p, PositionableIcon l, boolean right, double fromPoint) { 8968 l.rotate(-90); 8969 int offsetx = (int) (p.getX() + offSetFromPoint + fromPoint); 8970 int offsety = 0; 8971 if (right) { 8972 offsety = (int) p.getY() - (offSetFromPoint - 1) - l.maxHeight(); 8973 } else { 8974 offsety = (int) p.getY() + (offSetFromPoint); 8975 } 8976 return new Point(offsetx, offsety); 8977 } 8978 8979 // Come back to this as its a bit tight to the rail on SM110 need re 8980 // checking 8981 Point northEastToSouthWest(Point2D p, PositionableIcon l, int oldWidth, int oldHeight, double angleDEG, boolean right, double fromPoint) { 8982 angleDEG = angleDEG - 180; 8983 if (angleDEG < 45) { 8984 //Because of the angle things get shifted about. 8985 int tmpWidth = oldWidth; 8986 oldWidth = oldHeight; 8987 oldHeight = tmpWidth; 8988 } 8989 double ang = angleDEG; 8990 double oppAng = 90 - ang; 8991 double angleRAD = Math.toRadians(angleDEG); 8992 double oppAngRAD = Math.toRadians(oppAng); 8993 double iconAdj = Math.sin(angleRAD) * oldHeight; 8994 double iconAdjOpp = Math.sin(oppAngRAD) * oldHeight; 8995 double bpa = Math.sin(angleRAD) * (offSetFromPoint + fromPoint); 8996 double bpo = Math.sin(oppAngRAD) * (offSetFromPoint + fromPoint); 8997 double ta = Math.sin(angleRAD) * offSetFromPoint; 8998 double to = Math.sin(oppAngRAD) * offSetFromPoint; 8999 9000 if (log.isDebugEnabled()) { 9001 log.debug("north east to south west {}", angleDEG); 9002 log.debug("oldWidth {} oldHeight {}", oldWidth, oldHeight); 9003 log.debug("newWidth {} newHeight {}", l.maxWidth(), l.maxHeight()); 9004 log.debug("Icon adj: {} opp adj: {}", iconAdj, iconAdjOpp); 9005 log.debug("boundary point opp {}", bpo); 9006 log.debug("boundary point adj {}", bpa); 9007 log.debug("track opp {}", to); 9008 log.debug("track adj {}", ta); 9009 } 9010 int xpos = 0; 9011 int ypos = 0; 9012 if (right) { 9013 //double x_dist_to_Icon = (l.maxWidth()-iconAdj)-(bpa-bpo); 9014 //double y_dist_to_Icon = bpa+bpo+l.maxHeight(); 9015 9016 double x_dist_to_Icon = (iconAdjOpp) - (bpa - to); 9017 double y_dist_to_Icon = ta + bpo + l.maxHeight(); 9018 9019 log.debug("x dist {}, y dist {}", x_dist_to_Icon, y_dist_to_Icon); 9020 9021 xpos = (int) (p.getX() - x_dist_to_Icon); 9022 ypos = (int) (p.getY() - y_dist_to_Icon); 9023 9024 } else { 9025 double y_dist_to_Icon = iconAdjOpp + (bpo - ta); 9026 double x_dist_to_Icon = to + bpa; 9027 //double y_dist_to_Icon = (l.maxHeight()-iconAdj)-(ta-bpo); 9028 //double x_dist_to_Icon = bpa+to; 9029 log.debug("x dist {}, y dist {}", x_dist_to_Icon, y_dist_to_Icon); 9030 9031 xpos = (int) (p.getX() + x_dist_to_Icon); 9032 ypos = (int) (p.getY() - y_dist_to_Icon); 9033 9034 } 9035 if (log.isDebugEnabled()) { 9036 log.debug("xpos {}", xpos); 9037 log.debug("yPos {}", ypos); 9038 } 9039 return new Point(xpos, ypos); 9040 9041 } 9042 9043 Point southWestToNorthEast(Point2D p, PositionableIcon l, int oldWidth, int oldHeight, double angleDEG, boolean right, double fromPoint) { 9044 angleDEG = 180 - angleDEG; 9045 9046 double oppAng = angleDEG; 9047 double angDEG = 90 - oppAng; 9048 9049 //Because of the angle things get shifted about. 9050 if (angDEG < 45) { //was angle 9051 int tmpWidth = oldWidth; 9052 oldWidth = oldHeight; 9053 oldHeight = tmpWidth; 9054 } 9055 9056 double angRAD = Math.toRadians(angDEG); 9057 double oppAngRAD = Math.toRadians(oppAng); 9058 double iconAdj = Math.sin(angRAD) * oldHeight; 9059 double iconAdjOpp = Math.sin(oppAngRAD) * oldHeight; 9060 double bpa = Math.sin(angRAD) * (offSetFromPoint + fromPoint); 9061 double bpo = Math.sin(oppAngRAD) * (offSetFromPoint + fromPoint); 9062 double ta = Math.sin(angRAD) * offSetFromPoint; 9063 double to = Math.sin(oppAngRAD) * offSetFromPoint; 9064 9065 if (log.isDebugEnabled()) { 9066 log.debug("south west to north east {}", angleDEG); 9067 log.debug("oldWidth {} oldHeight {}", oldWidth, oldHeight); 9068 log.debug("newWidth {} newHeight {}", l.maxWidth(), l.maxHeight()); 9069 log.debug("Icon adj: {} opp adj: {}", iconAdj, iconAdjOpp); 9070 log.debug("boundary point opp {}", bpo); 9071 log.debug("boundary point adj {}", bpa); 9072 log.debug("track opp {}", to); 9073 log.debug("track adj {}", ta); 9074 } 9075 9076 int xpos; 9077 int ypos; 9078 9079 if (right) { 9080 double x_dist_to_Icon = iconAdj + (bpa - to); 9081 double y_dist_to_Icon = ta + bpo; 9082 log.debug("x dist {}, y dist {}", x_dist_to_Icon, y_dist_to_Icon); 9083 9084 xpos = (int) (p.getX() - x_dist_to_Icon); 9085 log.debug("xpos {}", xpos); 9086 ypos = (int) (p.getY() + y_dist_to_Icon); 9087 log.debug("yPos {}", ypos); 9088 } else { 9089 double x_dist_to_Icon = (bpa + to) + l.maxWidth(); 9090 //double y_dist_to_Icon = (iconAdj+(ta-bpo)); 9091 double y_dist_to_Icon = (bpo - ta) - (l.maxHeight() - iconAdjOpp); 9092 //double y_dist_to_Icon = (iconAdj+(ta-bpo)); 9093 log.debug("x dist {}, y dist {}", x_dist_to_Icon, y_dist_to_Icon); 9094 xpos = (int) (p.getX() - x_dist_to_Icon); 9095 ypos = (int) (p.getY() + y_dist_to_Icon); 9096 } 9097 if (log.isDebugEnabled()) { 9098 log.debug("xpos {}", xpos); 9099 log.debug("yPos {}", ypos); 9100 } 9101 return new Point(xpos, ypos); 9102 9103 } 9104 9105 //Working FOR SM140, SM81, sm120 9106 Point northWestToSouthEast(Point2D p, PositionableIcon l, int oldWidth, int oldHeight, double angleDEG, boolean right, double fromPoint) { 9107 log.debug("angle before {}", angleDEG); 9108 angleDEG = 180 - angleDEG; 9109 angleDEG = 90 - angleDEG; 9110 log.debug("north west to south east {}", angleDEG); 9111 if (angleDEG < 45) { 9112 //Because of the angle things get shifted about. 9113 int tmpWidth = oldWidth; 9114 oldWidth = oldHeight; 9115 oldHeight = tmpWidth; 9116 } 9117 log.debug("oldWidth {} oldHeight {}", oldWidth, oldHeight); 9118 log.debug("newWidth {} newHeight {}", l.maxWidth(), l.maxHeight()); 9119 //double ang = angle; 9120 double oppAng = 90 - angleDEG; 9121 double angleRAD = Math.toRadians(angleDEG); 9122 double oppAngRAD = Math.toRadians(oppAng); 9123 double iconAdj = Math.sin(angleRAD) * oldHeight; 9124 double iconAdjOpp = Math.sin(oppAngRAD) * oldHeight; 9125 9126 double bpa = Math.sin(angleRAD) * (offSetFromPoint + fromPoint); //distance from point 9127 double bpo = Math.sin(oppAngRAD) * (offSetFromPoint + fromPoint); 9128 double ta = Math.sin(angleRAD) * offSetFromPoint; //distance from track 9129 double to = Math.sin(oppAngRAD) * offSetFromPoint; 9130 9131 if (log.isDebugEnabled()) { 9132 log.debug("north west to south east {}", angleDEG); 9133 log.debug("oldWidth {} oldHeight {}", oldWidth, oldHeight); 9134 log.debug("newWidth {} newHeight {}", l.maxWidth(), l.maxHeight()); 9135 log.debug("Icon adj: {} opp adj: {}", iconAdj, iconAdjOpp); 9136 log.debug("boundary point opp {}", bpo); 9137 log.debug("boundary point adj {}", bpa); 9138 log.debug("track opp {}", to); 9139 log.debug("track adj {}", ta); 9140 } 9141 int xpos = 0; 9142 int ypos = 0; 9143 if (right) { 9144 //double x_dist_to_Icon = bpa+bpo+l.maxWidth(); 9145 //double y_dist_to_Icon = bpa-(l.maxHeight()-iconAdj); 9146 double x_dist_to_Icon = (l.maxWidth() + ta + bpo); 9147 double y_dist_to_Icon = iconAdj + (bpa - to); 9148 9149 log.debug("right x dist {}, y dist {}", x_dist_to_Icon, y_dist_to_Icon); 9150 9151 xpos = (int) (p.getX() - x_dist_to_Icon); 9152 ypos = (int) (p.getY() - y_dist_to_Icon); //was + 9153 } else { 9154 //This still needs to be worked out. 9155 //double y_dist_to_Icon = bpa+bpo+l.maxHeight(); 9156 //double x_dist_to_Icon = iconAdj+(bpa-bpo); 9157 9158 double y_dist_to_Icon = l.maxHeight() + bpa + to;//+(l.maxWidth()-iconAdj); 9159 //double y_dist_to_Icon = bpa-(l.maxHeight()-iconAdj); 9160 //double y_dist_to_Icon = ta+bpo+l.maxHeight(); 9161 double x_dist_to_Icon = (iconAdjOpp) + (bpo - ta); 9162 //double x_dist_to_Icon = iconAdj+(bpa-to); 9163 log.debug("left x dist {}, y dist {}", x_dist_to_Icon, y_dist_to_Icon); 9164 9165 xpos = (int) (p.getX() - x_dist_to_Icon); 9166 ypos = (int) (p.getY() - y_dist_to_Icon); 9167 } 9168 if (log.isDebugEnabled()) { 9169 log.debug("{} xpos {}", p.getX(), xpos); 9170 log.debug("{} yPos {}", p.getY(), ypos); 9171 } 9172 return new Point(xpos, ypos); 9173 } 9174 9175 double adjust = (5.0 / 90.0); 9176 int awayright = 5; 9177 private final int offSetFromPoint = 5; 9178 9179 //Correct for SM111, sm101, sm121, SM80 9180 Point southEastToNorthWest(Point2D p, PositionableIcon l, int oldWidth, int oldHeight, double angleDEG, boolean right, double fromPoint) { 9181 angleDEG = 360 - angleDEG; 9182 9183 if (angleDEG > 45) { 9184 //Because of the angle things get shifted about. 9185 int tmpWidth = oldWidth; 9186 int tmpHeight = oldHeight; 9187 oldWidth = tmpWidth; 9188 oldHeight = tmpHeight; 9189 } 9190 9191 // double ang = angle; 9192 double oppAng = 90 - angleDEG; 9193 double angleRAD = Math.toRadians(angleDEG); 9194 double oppAngRAD = Math.toRadians(oppAng); 9195 double iconAdj = Math.sin(angleRAD) * oldHeight; 9196 double iconAdjOpp = Math.sin(oppAngRAD) * oldHeight; 9197 double bpa = Math.sin(angleRAD) * (offSetFromPoint + fromPoint); 9198 double bpo = Math.sin(oppAngRAD) * (offSetFromPoint + fromPoint); 9199 double ta = Math.sin(angleRAD) * offSetFromPoint; //distance from track 9200 double to = Math.sin(oppAngRAD) * offSetFromPoint; 9201 if (log.isDebugEnabled()) { 9202 log.debug("south east to north west {}", angleDEG); 9203 log.debug("oldWidth {} oldHeight {}", oldWidth, oldHeight); 9204 log.debug("newWidth {} newHeight {}", l.maxWidth(), l.maxHeight()); 9205 log.debug("Icon adj: {} opp adj: {}", iconAdj, iconAdjOpp); 9206 log.debug("boundary point opp {}", bpo); 9207 log.debug("boundary point adj {}", bpa); 9208 log.debug("track opp {}", to); 9209 log.debug("track adj {}", ta); 9210 } 9211 int xpos = 0; 9212 int ypos = 0; 9213 if (right) { 9214 //double x_dist_to_Icon = bpa+bpo; 9215 //double y_dist_to_Icon = (iconAdj+bpa-bpo); 9216 double x_dist_to_Icon = bpa + to; 9217 double y_dist_to_Icon = (bpo - ta) - (l.maxHeight() - iconAdjOpp); 9218 9219 log.debug("ydist {}", Double.toString((bpo - ta) - (l.maxHeight() - iconAdjOpp))); 9220 log.debug(" and {}",Double.toString(bpo - (iconAdj + ta))); 9221 /*if(angleDeg<45){ 9222 y_dist_to_Icon = (bpo-ta)-(l.maxHeight()-iconAdjOpp); 9223 } else { 9224 y_dist_to_Icon = bpo-(iconAdj+ta); 9225 }*/ 9226 //double y_dist_to_Icon = (l.maxHeight()-iconAdj)+(bpo-ta); 9227 xpos = (int) (p.getX() + x_dist_to_Icon); 9228 ypos = (int) (p.getY() + y_dist_to_Icon); 9229 log.debug("right x dist {}, y dist {}", x_dist_to_Icon, y_dist_to_Icon); 9230 } else { 9231 //double x_dist_to_Icon = l.maxWidth()-(iconAdj+(bpa-bpo)); 9232 //double y_dist_to_Icon = bpa+bpo; 9233 9234 double x_dist_to_Icon = (bpa - to) - (l.maxWidth() - iconAdj); 9235 double y_dist_to_Icon = bpo + ta; 9236 9237 xpos = (int) (p.getX() + x_dist_to_Icon); 9238 ypos = (int) (p.getY() + y_dist_to_Icon); 9239 log.debug("left x dist {}, y dist {}", x_dist_to_Icon, y_dist_to_Icon); 9240 } 9241 if (log.isDebugEnabled()) { 9242 log.debug("{} xpos {}", p.getX(), xpos); 9243 log.debug("{} yPos {}", p.getY(), ypos); 9244 } 9245 9246 return new Point(xpos, ypos); 9247 } 9248 9249 public boolean isSignalMastOnPanel(@Nonnull SignalMast signalMast) { 9250 for (SignalMastIcon s : layoutEditor.getSignalMastList()) { 9251 if (s.getSignalMast() == signalMast) { 9252 return true; 9253 } 9254 } 9255 return false; 9256 } 9257 9258 /*=========================*\ 9259 |* setSignalMastsAtTurnout *| 9260 \*=========================*/ 9261 private JmriJFrame setSignalMastsAtTurnoutFrame = null; 9262 private boolean setSignalMastsAtTurnoutOpenFlag = false; 9263 private boolean setSignalMastsAtTurnoutFromMenuFlag = false; 9264 9265 private final NamedBeanComboBox<Turnout> signalMastsTurnoutComboBox = new NamedBeanComboBox<>( 9266 InstanceManager.turnoutManagerInstance(), null, 9267 DisplayOptions.DISPLAYNAME); 9268 9269 private JButton setSignalMastsDone; 9270 private JButton getSavedSignalMasts; 9271 private JButton setSignalMastsCancel; 9272 private JLabel turnoutMastNameLabel = null; 9273 9274 BeanDetails<SignalMast> turnoutSignalMastA; 9275 BeanDetails<SignalMast> turnoutSignalMastB; 9276 BeanDetails<SignalMast> turnoutSignalMastC; 9277 BeanDetails<SignalMast> turnoutSignalMastD; 9278 9279 JPanel signalMastTurnoutPanel = new JPanel(new FlowLayout()); 9280 9281 private String[] turnoutBlocks = new String[4]; 9282 9283 public void setSignalMastsAtTurnoutFromMenu(@Nonnull LayoutTurnout to, 9284 @Nonnull String[] blocks) { 9285 layoutTurnout = to; 9286 turnout = to.getTurnout(); 9287 signalMastsTurnoutComboBox.setSelectedItem(turnout); 9288 turnoutBlocks = new String[4]; 9289 for (int i = 0; i < blocks.length; i++) { 9290 turnoutBlocks[i] = blocks[i]; 9291 } 9292 setSignalMastsAtTurnoutFromMenuFlag = true; 9293 setSignalMastsAtTurnout(); 9294 setSignalMastsAtTurnoutFromMenuFlag = false; 9295 } 9296 9297 //TODO: Add to Tools menu? 9298 public void setSignalMastsAtTurnout() { 9299 9300 //Initialize if needed 9301 if (setSignalMastsAtTurnoutFrame == null) { 9302 setSignalMastsAtTurnoutOpenFlag = false; 9303 9304 turnoutSignalMastA = new BeanDetails<>("SignalMast", // NOI18N 9305 InstanceManager.getDefault(SignalMastManager.class)); 9306 turnoutSignalMastB = new BeanDetails<>("SignalMast", // NOI18N 9307 InstanceManager.getDefault(SignalMastManager.class)); 9308 turnoutSignalMastC = new BeanDetails<>("SignalMast", // NOI18N 9309 InstanceManager.getDefault(SignalMastManager.class)); 9310 turnoutSignalMastD = new BeanDetails<>("SignalMast", // NOI18N 9311 InstanceManager.getDefault(SignalMastManager.class)); 9312 9313 turnoutSignalMastA.getDetailsPanel().setBackground(new Color(255, 255, 200)); 9314 turnoutSignalMastB.getDetailsPanel().setBackground(new Color(200, 255, 255)); 9315 turnoutSignalMastC.getDetailsPanel().setBackground(new Color(200, 200, 255)); 9316 turnoutSignalMastD.getDetailsPanel().setBackground(new Color(255, 200, 200)); 9317 9318 setSignalMastsAtTurnoutFrame = new JmriJFrame(Bundle.getMessage("SignalMastsAtTurnout"), false, true); 9319 oneFrameToRuleThemAll(setSignalMastsAtTurnoutFrame); 9320 setSignalMastsAtTurnoutFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 9321// setSignalMastsAtTurnoutFrame.addHelpMenu("package.jmri.jmrit.display.SetSignalMastsAtTurnout", true); 9322 setSignalMastsAtTurnoutFrame.setLocation(70, 30); 9323 Container theContentPane = setSignalMastsAtTurnoutFrame.getContentPane(); 9324 theContentPane.setLayout(new BoxLayout(theContentPane, BoxLayout.Y_AXIS)); 9325 9326 JPanel panel1 = new JPanel(new FlowLayout()); 9327 9328 turnoutMastNameLabel = new JLabel( 9329 Bundle.getMessage("BeanNameTurnout") 9330 + " " + Bundle.getMessage("Name")); 9331 panel1.add(turnoutMastNameLabel); 9332 panel1.add(signalMastsTurnoutComboBox); 9333 signalMastsTurnoutComboBox.setToolTipText(Bundle.getMessage("SignalMastsTurnoutNameHint")); 9334 9335 theContentPane.add(panel1); 9336 theContentPane.add(new JSeparator(JSeparator.HORIZONTAL)); 9337 9338 JPanel panel2 = new JPanel(new FlowLayout()); 9339 JLabel shTitle = new JLabel(Bundle.getMessage("SignalMasts")); 9340 panel2.add(shTitle); 9341 panel2.add(new JLabel(" ")); 9342 panel2.add(getSavedSignalMasts = new JButton(Bundle.getMessage("GetSaved"))); 9343 getSavedSignalMasts.addActionListener(this::turnoutSignalMastsGetSaved); 9344 getSavedSignalMasts.setToolTipText(Bundle.getMessage("GetSavedHint")); 9345 theContentPane.add(panel2); 9346 9347 signalMastTurnoutPanel.setLayout(new GridLayout(0, 2)); 9348 theContentPane.add(signalMastTurnoutPanel); 9349 theContentPane.add(new JSeparator(JSeparator.HORIZONTAL)); 9350 9351 JPanel panel6 = new JPanel(new FlowLayout()); 9352 panel6.add(new JLabel(" ")); 9353 panel6.add(setSignalMastsDone = new JButton(Bundle.getMessage("ButtonDone"))); 9354 setSignalMastsDone.addActionListener(this::setSignalMastsDonePressed); 9355 setSignalMastsDone.setToolTipText(Bundle.getMessage("DoneHint", Bundle.getMessage("ButtonDone"))); 9356 9357 panel6.add(setSignalMastsCancel = new JButton(Bundle.getMessage("ButtonCancel"))); 9358 setSignalMastsCancel.addActionListener(this::setSignalMastsCancelPressed); 9359 setSignalMastsCancel.setToolTipText(Bundle.getMessage("CancelHint", Bundle.getMessage("ButtonCancel"))); 9360 theContentPane.add(panel6); 9361 9362//make this button the default button (return or enter activates) 9363 JRootPane rootPane = SwingUtilities.getRootPane(setSignalMastsDone); 9364 if (rootPane != null) { 9365 rootPane.setDefaultButton(setSignalMastsDone); 9366 } 9367 } 9368 9369 turnoutSignalMastA.getCombo().setExcludedItems(new HashSet<>()); 9370 turnoutSignalMastB.getCombo().setExcludedItems(new HashSet<>()); 9371 turnoutSignalMastC.getCombo().setExcludedItems(new HashSet<>()); 9372 turnoutSignalMastD.getCombo().setExcludedItems(new HashSet<>()); 9373 signalMastTurnoutPanel.removeAll(); 9374 9375 signalMastsTurnoutComboBox.setVisible(!setSignalMastsAtTurnoutFromMenuFlag); 9376 9377 if (setSignalMastsAtTurnoutFromMenuFlag) { 9378 turnoutMastNameLabel.setText(Bundle.getMessage("MakeLabel", 9379 Bundle.getMessage("BeanNameTurnout") 9380 + " " + Bundle.getMessage("Name")) 9381 + " " + layoutTurnout.getTurnoutName()); 9382 } 9383 9384 if (!setSignalMastsAtTurnoutOpenFlag) { 9385 setSignalMastsAtTurnoutFrame.setPreferredSize(null); 9386 setSignalMastsAtTurnoutFrame.pack(); 9387 setSignalMastsAtTurnoutOpenFlag = true; 9388 } 9389 refreshSignalMastAtTurnoutComboBox(); 9390 setSignalMastsAtTurnoutFrame.setVisible(true); 9391 } //setSignalMastsAtTurnout 9392 9393 private void turnoutSignalMastsGetSaved(ActionEvent a) { 9394 if (!getTurnoutMastInformation()) { 9395 return; 9396 } 9397 turnoutBlocks = layoutTurnout.getBlockBoundaries(); 9398 9399 turnoutSignalMastA.setTextField(layoutTurnout.getSignalAMastName()); 9400 turnoutSignalMastB.setTextField(layoutTurnout.getSignalBMastName()); 9401 turnoutSignalMastC.setTextField(layoutTurnout.getSignalCMastName()); 9402 turnoutSignalMastD.setTextField(layoutTurnout.getSignalDMastName()); 9403 9404 turnoutSignalMastA.setBoundaryLabel(turnoutBlocks[0]); 9405 turnoutSignalMastB.setBoundaryLabel(turnoutBlocks[1]); 9406 turnoutSignalMastC.setBoundaryLabel(turnoutBlocks[2]); 9407 turnoutSignalMastD.setBoundaryLabel(turnoutBlocks[3]); 9408 9409 signalMastTurnoutPanel.removeAll(); 9410 boolean boundaryFlag = false; 9411 if (turnoutBlocks[0] != null) { 9412 signalMastTurnoutPanel.add(turnoutSignalMastA.getDetailsPanel()); 9413 boundaryFlag = true; 9414 } 9415 if (turnoutBlocks[1] != null) { 9416 signalMastTurnoutPanel.add(turnoutSignalMastB.getDetailsPanel()); 9417 boundaryFlag = true; 9418 } 9419 if (turnoutBlocks[2] != null) { 9420 signalMastTurnoutPanel.add(turnoutSignalMastC.getDetailsPanel()); 9421 boundaryFlag = true; 9422 } 9423 if (turnoutBlocks[3] != null) { 9424 signalMastTurnoutPanel.add(turnoutSignalMastD.getDetailsPanel()); 9425 boundaryFlag = true; 9426 } 9427 if (!boundaryFlag) { 9428 JmriJOptionPane.showMessageDialog(null, Bundle.getMessage("SignalsError20")); 9429 } 9430 setSignalMastsAtTurnoutFrame.setPreferredSize(null); 9431 setSignalMastsAtTurnoutFrame.pack(); 9432 } //turnoutSignalMastsGetSaved 9433 9434 private void setSignalMastsDonePressed(ActionEvent a) { 9435 //process turnout name 9436 if (!getTurnoutMastInformation()) { 9437 return; 9438 } 9439 9440 //process signal head names 9441 SignalMast turnoutMast = getSignalMastFromEntry(turnoutSignalMastA.getText(), false, setSignalsAtTurnoutFrame); 9442 SignalMast turnoutMastB = getSignalMastFromEntry(turnoutSignalMastB.getText(), false, setSignalsAtTurnoutFrame); 9443 SignalMast turnoutMastC = getSignalMastFromEntry(turnoutSignalMastC.getText(), false, setSignalsAtTurnoutFrame); 9444 SignalMast turnoutMastD = getSignalMastFromEntry(turnoutSignalMastD.getText(), false, setSignalsAtTurnoutFrame); 9445 9446 LayoutTurnoutView layoutTurnoutView = layoutEditor.getLayoutTurnoutView(layoutTurnout); 9447 9448 //place signals as requested 9449 if (turnoutSignalMastA.addToPanel() && (turnoutMast != null)) { 9450 if (isSignalMastOnPanel(turnoutMast) 9451 && (turnoutMast != layoutTurnout.getSignalAMast())) { 9452 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 9453 Bundle.getMessage("SignalsError6", 9454 new Object[]{turnoutSignalMastA.getText()}), 9455 Bundle.getMessage("ErrorTitle"), 9456 JmriJOptionPane.ERROR_MESSAGE); 9457 return; 9458 } else { 9459 removeSignalMastFromPanel(layoutTurnout.getSignalAMast()); 9460 SignalMastIcon l = new SignalMastIcon(layoutEditor); 9461 l.setSignalMast(turnoutSignalMastA.getText()); 9462 placingBlock(l, turnoutSignalMastA.isRightSelected(), 9463 0.0, layoutTurnout.getConnectA(), layoutTurnoutView.getCoordsA()); 9464 removeAssignment(turnoutMast); 9465 layoutTurnout.setSignalAMast(turnoutSignalMastA.getText()); 9466 needRedraw = true; 9467 } 9468 } else if (turnoutMast != null) { 9469 LayoutTurnout.Geometry assigned = isMastAssignedHere(turnoutMast, layoutTurnout); 9470 if (assigned == LayoutTurnout.Geometry.NONE) { 9471 if (isSignalMastOnPanel(turnoutMast) 9472 && isSignalMastAssignedAnywhere(turnoutMast)) { 9473 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 9474 Bundle.getMessage("SignalsError8", 9475 new Object[]{turnoutSignalMastA.getText()}), 9476 Bundle.getMessage("ErrorTitle"), 9477 JmriJOptionPane.ERROR_MESSAGE); 9478 return; 9479 } else { 9480 removeSignalMastFromPanel(layoutTurnout.getSignalAMast()); 9481 removeAssignment(turnoutMast); 9482 layoutTurnout.setSignalAMast(turnoutSignalMastA.getText()); 9483 } 9484 //} else if (assigned != A1) { 9485 //need to figure out what to do in this case. 9486 } 9487 } else { 9488 removeSignalMastFromPanel(layoutTurnout.getSignalAMast()); 9489 layoutTurnout.setSignalAMast(""); 9490 } 9491 if ((turnoutSignalMastB.addToPanel()) && (turnoutMastB != null)) { 9492 if (isSignalMastOnPanel(turnoutMastB) 9493 && (turnoutMastB != layoutTurnout.getSignalBMast())) { 9494 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 9495 Bundle.getMessage("SignalsError6", 9496 new Object[]{turnoutSignalMastB.getText()}), 9497 Bundle.getMessage("ErrorTitle"), 9498 JmriJOptionPane.ERROR_MESSAGE); 9499 return; 9500 } else { 9501 removeSignalMastFromPanel(layoutTurnout.getSignalBMast()); 9502 SignalMastIcon l = new SignalMastIcon(layoutEditor); 9503 l.setSignalMast(turnoutSignalMastB.getText()); 9504 placingBlock(l, turnoutSignalMastB.isRightSelected(), 9505 0.0, layoutTurnout.getConnectB(), layoutTurnoutView.getCoordsB()); 9506 removeAssignment(turnoutMastB); 9507 layoutTurnout.setSignalBMast(turnoutSignalMastB.getText()); 9508 needRedraw = true; 9509 } 9510 } else if (turnoutMastB != null) { 9511 LayoutTurnout.Geometry assigned = isMastAssignedHere(turnoutMastB, layoutTurnout); 9512 if (assigned == LayoutTurnout.Geometry.NONE) { 9513 if (isSignalMastOnPanel(turnoutMastB) 9514 && isSignalMastAssignedAnywhere(turnoutMastB)) { 9515 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 9516 Bundle.getMessage("SignalsError8", 9517 new Object[]{turnoutSignalMastB.getText()}), 9518 Bundle.getMessage("ErrorTitle"), 9519 JmriJOptionPane.ERROR_MESSAGE); 9520 return; 9521 } else { 9522 removeSignalMastFromPanel(layoutTurnout.getSignalBMast()); 9523 removeAssignment(turnoutMastB); 9524 layoutTurnout.setSignalBMast(turnoutSignalMastB.getText()); 9525 } 9526 //} else if (assigned != A2) { 9527 //need to figure out what to do in this case. 9528 } 9529 } else { 9530 removeSignalMastFromPanel(layoutTurnout.getSignalBMast()); 9531 layoutTurnout.setSignalBMast(""); 9532 } 9533 if (turnoutMastC != null) { 9534 if (turnoutSignalMastC.addToPanel()) { 9535 if (isSignalMastOnPanel(turnoutMastC) 9536 && (turnoutMastC != layoutTurnout.getSignalCMast())) { 9537 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 9538 Bundle.getMessage("SignalsError6", 9539 new Object[]{turnoutSignalMastC.getText()}), 9540 Bundle.getMessage("ErrorTitle"), 9541 JmriJOptionPane.ERROR_MESSAGE); 9542 return; 9543 } else { 9544 removeSignalMastFromPanel(layoutTurnout.getSignalCMast()); 9545 SignalMastIcon l = new SignalMastIcon(layoutEditor); 9546 l.setSignalMast(turnoutSignalMastC.getText()); 9547 placingBlock(l, turnoutSignalMastC.isRightSelected(), 9548 0.0, layoutTurnout.getConnectC(), layoutTurnoutView.getCoordsC()); 9549 removeAssignment(turnoutMastC); 9550 layoutTurnout.setSignalCMast(turnoutSignalMastC.getText()); 9551 needRedraw = true; 9552 } 9553 } else { 9554 LayoutTurnout.Geometry assigned = isMastAssignedHere(turnoutMastC, layoutTurnout); 9555 if (assigned == LayoutTurnout.Geometry.NONE) { 9556 if (isSignalMastOnPanel(turnoutMastC) 9557 && isSignalMastAssignedAnywhere(turnoutMastC)) { 9558 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 9559 Bundle.getMessage("SignalsError8", 9560 new Object[]{turnoutSignalMastC.getText()}), 9561 Bundle.getMessage("ErrorTitle"), 9562 JmriJOptionPane.ERROR_MESSAGE); 9563 return; 9564 } else { 9565 removeSignalMastFromPanel(layoutTurnout.getSignalCMast()); 9566 removeAssignment(turnoutMastC); 9567 layoutTurnout.setSignalCMast(turnoutSignalMastC.getText()); 9568 } 9569 //} else if (assigned != A3) { 9570 //need to figure out what to do in this case. 9571 } 9572 } 9573 } else { 9574 removeSignalMastFromPanel(layoutTurnout.getSignalCMast()); 9575 layoutTurnout.setSignalCMast(""); 9576 } 9577 if (turnoutMastD != null) { 9578 if (turnoutSignalMastD.addToPanel()) { 9579 if (isSignalMastOnPanel(turnoutMastD) 9580 && (turnoutMastD != layoutTurnout.getSignalDMast())) { 9581 String signalHeadName = divergingSignalHeadComboBox.getSelectedItemDisplayName(); 9582 if (signalHeadName == null) { 9583 signalHeadName = ""; 9584 } 9585 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 9586 Bundle.getMessage("SignalsError6", 9587 new Object[]{signalHeadName}), 9588 Bundle.getMessage("ErrorTitle"), 9589 JmriJOptionPane.ERROR_MESSAGE); 9590 return; 9591 } else { 9592 removeSignalMastFromPanel(layoutTurnout.getSignalDMast()); 9593 SignalMastIcon l = new SignalMastIcon(layoutEditor); 9594 l.setSignalMast(turnoutSignalMastD.getText()); 9595 placingBlock(l, turnoutSignalMastD.isRightSelected(), 9596 0.0, layoutTurnout.getConnectD(), layoutTurnoutView.getCoordsD()); 9597 removeAssignment(turnoutMastD); 9598 layoutTurnout.setSignalDMast(turnoutSignalMastD.getText()); 9599 needRedraw = true; 9600 } 9601 } else { 9602 LayoutTurnout.Geometry assigned = isMastAssignedHere(turnoutMastD, layoutTurnout); 9603 if (assigned == LayoutTurnout.Geometry.NONE) { 9604 if (isSignalMastOnPanel(turnoutMastD) 9605 && isSignalMastAssignedAnywhere(turnoutMastD)) { 9606 JmriJOptionPane.showMessageDialog(setSignalsAtTurnoutFrame, 9607 Bundle.getMessage("SignalsError8", 9608 new Object[]{turnoutSignalMastD.getText()}), 9609 Bundle.getMessage("ErrorTitle"), 9610 JmriJOptionPane.ERROR_MESSAGE); 9611 return; 9612 } else { 9613 removeSignalMastFromPanel(layoutTurnout.getSignalDMast()); 9614 removeAssignment(turnoutMastD); 9615 layoutTurnout.setSignalDMast(turnoutSignalMastD.getText()); 9616 } 9617 //} else if (assigned != B1) { 9618 //need to figure out what to do in this case. 9619 } 9620 } 9621 } else { 9622 removeSignalMastFromPanel(layoutTurnout.getSignalDMast()); 9623 layoutTurnout.setSignalDMast(""); 9624 } 9625 9626 //make sure this layout turnout is not linked to another 9627 layoutTurnout.setLinkType(LayoutTurnout.LinkType.NO_LINK); 9628 layoutTurnout.setLinkedTurnoutName(""); 9629 //finish up 9630 setSignalMastsAtTurnoutOpenFlag = false; 9631 setSignalMastsAtTurnoutFrame.setVisible(false); 9632 if (needRedraw) { 9633 layoutEditor.redrawPanel(); 9634 needRedraw = false; 9635 layoutEditor.setDirty(); 9636 } 9637 } //setSignalMastsDonePressed 9638 9639 9640 Set<SignalMast> usedMasts = new HashSet<>(); 9641 9642 void createListUsedSignalMasts() { 9643 usedMasts = new HashSet<>(); 9644 for (PositionablePoint po : layoutEditor.getPositionablePoints()) { 9645 //We allow the same sensor to be allocated in both directions. 9646 if (po != boundary) { 9647 if (po.getEastBoundSignalMast() != null) { 9648 usedMasts.add(po.getEastBoundSignalMast()); 9649 } 9650 if (po.getWestBoundSignalMast() != null) { 9651 usedMasts.add(po.getWestBoundSignalMast()); 9652 } 9653 } 9654 } 9655 9656 for (LayoutTurnout to : layoutEditor.getLayoutTurnoutsAndSlips()) { 9657 if (to.getSignalAMast() != null) { 9658 usedMasts.add(to.getSignalAMast()); 9659 } 9660 if (to.getSignalBMast() != null) { 9661 usedMasts.add(to.getSignalBMast()); 9662 } 9663 if (to.getSignalCMast() != null) { 9664 usedMasts.add(to.getSignalCMast()); 9665 } 9666 if (to.getSignalDMast() != null) { 9667 usedMasts.add(to.getSignalDMast()); 9668 } 9669 } 9670 for (LevelXing x : layoutEditor.getLevelXings()) { 9671 if (x.getSignalAMast() != null) { 9672 usedMasts.add(x.getSignalAMast()); 9673 } 9674 if (x.getSignalBMast() != null) { 9675 usedMasts.add(x.getSignalBMast()); 9676 } 9677 if (x.getSignalCMast() != null) { 9678 usedMasts.add(x.getSignalCMast()); 9679 } 9680 if (x.getSignalDMast() != null) { 9681 usedMasts.add(x.getSignalDMast()); 9682 } 9683 } 9684 } //createListUsedSignalMasts 9685 9686 void refreshSignalMastAtTurnoutComboBox() { 9687 turnoutSignalMastsGetSaved(null); 9688