001package jmri.jmrit.display.layoutEditor; 002 003import java.awt.Color; 004import java.awt.Graphics2D; 005import java.awt.event.ActionEvent; 006import java.awt.geom.*; 007import static java.lang.Float.POSITIVE_INFINITY; 008import static java.lang.Math.PI; 009import java.util.*; 010 011import javax.annotation.CheckForNull; 012import javax.annotation.Nonnull; 013import javax.swing.*; 014 015import jmri.*; 016import jmri.jmrit.display.layoutEditor.LevelXing.Geometry; 017import jmri.jmrit.display.layoutEditor.blockRoutingTable.LayoutBlockRouteTableAction; 018import jmri.util.MathUtil; 019import jmri.util.swing.JmriMouseEvent; 020 021/** 022 * MVC View component for the LevelXing class 023 * 024 * @author Bob Jacobsen Copyright (c) 2020 025 * 026 */ 027public class LevelXingView extends LayoutTrackView { 028 029 /** 030 * Constructor method. 031 * @param xing the level crossing. 032 * @param layoutEditor for access to tools 033 */ 034 public LevelXingView(@Nonnull LevelXing xing, @Nonnull LayoutEditor layoutEditor) { 035 super(xing, layoutEditor); 036 037 this.xing = xing; 038 editor = new jmri.jmrit.display.layoutEditor.LayoutEditorDialogs.LevelXingEditor(layoutEditor); 039 } 040 041 /** 042 * constructor method 043 * @param xing the level crossing. 044 * @param c display location 045 * @param layoutEditor for access to tools 046 */ 047 public LevelXingView(@Nonnull LevelXing xing, @Nonnull Point2D c, @Nonnull LayoutEditor layoutEditor) { 048 super(xing, c, layoutEditor); 049 050 this.xing = xing; 051 editor = new jmri.jmrit.display.layoutEditor.LayoutEditorDialogs.LevelXingEditor(layoutEditor); 052 } 053 054 private Point2D dispA = new Point2D.Double(-20.0, 0.0); 055 private Point2D dispB = new Point2D.Double(-14.0, 14.0); 056 057 // temporary reference to the Editor that will eventually be part of View 058 private final jmri.jmrit.display.layoutEditor.LayoutEditorDialogs.LevelXingEditor editor; 059 060 final private LevelXing xing; 061 062 // temporary? 063 @Nonnull 064 public LevelXing getLevelXing() { return xing; } 065 066 // this should only be used for debugging 067 @Override 068 public String toString() { 069 return "LevelXing " + getName(); 070 } 071 072 /* 073 * Accessor methods 074 */ 075 @Nonnull 076 public String getBlockNameAC() { 077 return xing.getBlockNameAC(); 078 } 079 080 @Nonnull 081 public String getBlockNameBD() { 082 return xing.getBlockNameBD(); 083 } 084 085 public SignalHead getSignalHead(Geometry loc) { 086 return xing.getSignalHead(loc); 087 } 088 089 public SignalMast getSignalMast(Geometry loc) { 090 return xing.getSignalMast(loc); 091 } 092 093 public Sensor getSensor(Geometry loc) { 094 return xing.getSensor(loc); 095 } 096 097 @Nonnull 098 public String getSignalAName() { 099 return xing.getSignalAName(); 100 } 101 102 public void setSignalAName(String signalHead) { 103 xing.setSignalAName(signalHead); 104 } 105 106 @Nonnull 107 public String getSignalBName() { 108 return xing.getSignalBName(); 109 } 110 111 public void setSignalBName(String signalHead) { 112 xing.setSignalBName(signalHead); 113 } 114 115 @Nonnull 116 public String getSignalCName() { 117 return xing.getSignalCName(); 118 } 119 120 public void setSignalCName(String signalHead) { 121 xing.setSignalCName(signalHead); 122 } 123 124 @Nonnull 125 public String getSignalDName() { 126 return xing.getSignalDName(); 127 } 128 129 public void setSignalDName(String signalHead) { 130 xing.setSignalDName(signalHead); 131 } 132 133 public void removeBeanReference(jmri.NamedBean nb) { 134 xing.removeBeanReference(nb); 135 } 136 137 public String getSignalAMastName() { 138 return xing.getSignalAMastName(); 139 } 140 141 public SignalMast getSignalAMast() { 142 return xing.getSignalAMast(); 143 } 144 145 public void setSignalAMast(String signalMast) { 146 xing.setSignalAMast(signalMast); 147 } 148 149 public String getSignalBMastName() { 150 return xing.getSignalBMastName(); 151 } 152 153 public SignalMast getSignalBMast() { 154 return xing.getSignalBMast(); 155 } 156 157 public void setSignalBMast(String signalMast) { 158 xing.setSignalBMast(signalMast); 159 } 160 161 public String getSignalCMastName() { 162 return xing.getSignalCMastName(); 163 } 164 165 public SignalMast getSignalCMast() { 166 return xing.getSignalCMast(); 167 } 168 169 public void setSignalCMast(String signalMast) { 170 xing.setSignalCMast(signalMast); 171 } 172 173 public String getSignalDMastName() { 174 return xing.getSignalDMastName(); 175 } 176 177 public SignalMast getSignalDMast() { 178 return xing.getSignalDMast(); 179 } 180 181 public void setSignalDMast(String signalMast) { 182 xing.setSignalDMast(signalMast); 183 } 184 185 public String getSensorAName() { 186 return xing.getSensorAName(); 187 } 188 189 public Sensor getSensorA() { 190 return xing.getSensorA(); 191 } 192 193 public void setSensorAName(String sensorName) { 194 xing.setSensorAName(sensorName); 195 } 196 197 public String getSensorBName() { 198 return xing.getSensorBName(); 199 } 200 201 public Sensor getSensorB() { 202 return xing.getSensorB(); 203 } 204 205 public void setSensorBName(String sensorName) { 206 xing.setSensorBName(sensorName); 207 } 208 209 public String getSensorCName() { 210 return xing.getSensorCName(); 211 } 212 213 public Sensor getSensorC() { 214 return xing.getSensorC(); 215 } 216 217 public void setSensorCName(String sensorName) { 218 xing.setSensorCName(sensorName); 219 } 220 221 public String getSensorDName() { 222 return xing.getSensorDName(); 223 } 224 225 public Sensor getSensorD() { 226 return xing.getSensorD(); 227 } 228 229 public void setSensorDName(String sensorName) { 230 xing.setSensorDName(sensorName); 231 } 232 233 /** 234 * {@inheritDoc} 235 */ 236 @Override 237 public LayoutTrack getConnection(HitPointType connectionType) throws jmri.JmriException { 238 return xing.getConnection(connectionType); 239 } 240 241 /** 242 * {@inheritDoc} 243 */ 244 @Override 245 public void setConnection(HitPointType connectionType, LayoutTrack o, HitPointType type) throws jmri.JmriException { 246 xing.setConnection(connectionType, o, type); 247 } 248 249 public LayoutTrack getConnectA() { 250 return xing.getConnectA(); 251 } 252 253 public LayoutTrack getConnectB() { 254 return xing.getConnectB(); 255 } 256 257 public LayoutTrack getConnectC() { 258 return xing.getConnectC(); 259 } 260 261 public LayoutTrack getConnectD() { 262 return xing.getConnectD(); 263 } 264 265 public void setConnectA(LayoutTrack o, HitPointType type) { 266 xing.setConnectA(o, type); 267 } 268 269 public void setConnectB(LayoutTrack o, HitPointType type) { 270 xing.setConnectB(o, type); 271 } 272 273 public void setConnectC(LayoutTrack o, HitPointType type) { 274 xing.setConnectC(o, type); 275 } 276 277 public void setConnectD(LayoutTrack o, HitPointType type) { 278 xing.setConnectD(o, type); 279 } 280 281 public LayoutBlock getLayoutBlockAC() { 282 return xing.getLayoutBlockAC(); 283 } 284 285 public LayoutBlock getLayoutBlockBD() { 286 return xing.getLayoutBlockBD(); 287 } 288 289 290 291 public Point2D getCoordsA() { 292 return MathUtil.add(getCoordsCenter(), dispA); 293 } 294 295 public Point2D getCoordsB() { 296 return MathUtil.add(getCoordsCenter(), dispB); 297 } 298 299 public Point2D getCoordsC() { 300 return MathUtil.subtract(getCoordsCenter(), dispA); 301 } 302 303 public Point2D getCoordsD() { 304 return MathUtil.subtract(getCoordsCenter(), dispB); 305 } 306 307 /** 308 * Get the coordinates for a specified connection type. 309 * 310 * @param connectionType the connection type 311 * @return the coordinates for the specified connection type 312 */ 313 @Override 314 public Point2D getCoordsForConnectionType(HitPointType connectionType) { 315 Point2D result = getCoordsCenter(); 316 switch (connectionType) { 317 case LEVEL_XING_CENTER: 318 break; 319 case LEVEL_XING_A: 320 result = getCoordsA(); 321 break; 322 case LEVEL_XING_B: 323 result = getCoordsB(); 324 break; 325 case LEVEL_XING_C: 326 result = getCoordsC(); 327 break; 328 case LEVEL_XING_D: 329 result = getCoordsD(); 330 break; 331 default: 332 log.error("{}.getCoordsForConnectionType({}); Invalid connection type ", 333 getName(), connectionType); //I18IN 334 } 335 return result; 336 } 337 338 /** 339 * @return the bounds of this crossing 340 */ 341 @Override 342 public Rectangle2D getBounds() { 343 Rectangle2D result; 344 345 Point2D pointA = getCoordsA(); 346 result = new Rectangle2D.Double(pointA.getX(), pointA.getY(), 0, 0); 347 result.add(getCoordsB()); 348 result.add(getCoordsC()); 349 result.add(getCoordsD()); 350 return result; 351 } 352 353 /** 354 * Add Layout Blocks. 355 */ 356// @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", justification = "Null is accepted as a valid value") 357// public void setLayoutBlockAC(LayoutBlock newLayoutBlock) { 358// LayoutBlock blockAC = getLayoutBlockAC(); 359// LayoutBlock blockBD = getLayoutBlockBD(); 360// if (blockAC != newLayoutBlock) { 361// // block 1 has changed, if old block exists, decrement use 362// if ((blockAC != null) && (blockAC != blockBD)) { 363// blockAC.decrementUse(); 364// } 365// blockAC = newLayoutBlock; 366// if (newLayoutBlock != null) { 367// namedLayoutBlockAC = InstanceManager.getDefault(jmri.NamedBeanHandleManager.class).getNamedBeanHandle(newLayoutBlock.getUserName(), newLayoutBlock); 368// } else { 369// namedLayoutBlockAC = null; 370// } 371// 372// // decrement use if block was previously counted 373// if ((blockAC != null) && (blockAC == blockBD)) { 374// blockAC.decrementUse(); 375// } 376// } 377// } 378 379// @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", justification = "Null is accepted as a valid value") 380// public void setLayoutBlockBD(LayoutBlock newLayoutBlock) { 381// LayoutBlock blockAC = getLayoutBlockAC(); 382// LayoutBlock blockBD = getLayoutBlockBD(); 383// if (blockBD != newLayoutBlock) { 384// // block 1 has changed, if old block exists, decrement use 385// if ((blockBD != null) && (blockBD != blockAC)) { 386// blockBD.decrementUse(); 387// } 388// blockBD = newLayoutBlock; 389// if (newLayoutBlock != null) { 390// namedLayoutBlockBD = InstanceManager.getDefault(jmri.NamedBeanHandleManager.class).getNamedBeanHandle(newLayoutBlock.getUserName(), newLayoutBlock); 391// } else { 392// namedLayoutBlockBD = null; 393// } 394// // decrement use if block was previously counted 395// if ((blockBD != null) && (blockBD == blockAC)) { 396// blockBD.decrementUse(); 397// } 398// } 399// 400// } 401// 402// public void updateBlockInfo() { 403// LayoutBlock blockAC = getLayoutBlockAC(); 404// LayoutBlock blockBD = getLayoutBlockBD(); 405// LayoutBlock b1 = null; 406// LayoutBlock b2 = null; 407// if (blockAC != null) { 408// blockAC.updatePaths(); 409// } 410// if (connectA != null) { 411// b1 = ((TrackSegment) connectA).getLayoutBlock(); 412// if ((b1 != null) && (b1 != blockAC)) { 413// b1.updatePaths(); 414// } 415// } 416// if (connectC != null) { 417// b2 = ((TrackSegment) connectC).getLayoutBlock(); 418// if ((b2 != null) && (b2 != blockAC) && (b2 != b1)) { 419// b2.updatePaths(); 420// } 421// } 422// if (blockBD != null) { 423// blockBD.updatePaths(); 424// } 425// if (connectB != null) { 426// b1 = ((TrackSegment) connectB).getLayoutBlock(); 427// if ((b1 != null) && (b1 != blockBD)) { 428// b1.updatePaths(); 429// } 430// } 431// if (connectD != null) { 432// b2 = ((TrackSegment) connectD).getLayoutBlock(); 433// if ((b2 != null) && (b2 != blockBD) && (b2 != b1)) { 434// b2.updatePaths(); 435// } 436// } 437// reCheckBlockBoundary(); 438// } 439// 440// void removeSML(SignalMast signalMast) { 441// if (signalMast == null) { 442// return; 443// } 444// if (jmri.InstanceManager.getDefault(LayoutBlockManager.class).isAdvancedRoutingEnabled() && InstanceManager.getDefault(jmri.SignalMastLogicManager.class).isSignalMastUsed(signalMast)) { 445// SignallingGuiTools.removeSignalMastLogic(null, signalMast); 446// } 447// } 448 449 /** 450 * Test if mainline track or not. 451 * 452 * @return true if either connecting track segment is mainline; Defaults to 453 * not mainline if connecting track segments are missing 454 */ 455 public boolean isMainlineAC() { 456 return xing.isMainlineAC(); 457 } 458 459 public boolean isMainlineBD() { 460 return xing.isMainlineBD(); 461 } 462 463 /* 464 * Modify coordinates methods. 465 */ 466 public void setCoordsA(Point2D p) { 467 dispA = MathUtil.subtract(p, getCoordsCenter()); 468 } 469 470 public void setCoordsB(Point2D p) { 471 dispB = MathUtil.subtract(p, getCoordsCenter()); 472 } 473 474 public void setCoordsC(Point2D p) { 475 dispA = MathUtil.subtract(getCoordsCenter(), p); 476 } 477 478 public void setCoordsD(Point2D p) { 479 dispB = MathUtil.subtract(getCoordsCenter(), p); 480 } 481 482 /** 483 * {@inheritDoc} 484 */ 485 @Override 486 public void scaleCoords(double xFactor, double yFactor) { 487 Point2D factor = new Point2D.Double(xFactor, yFactor); 488 super.setCoordsCenter(MathUtil.granulize(MathUtil.multiply(getCoordsCenter(), factor), 1.0)); 489 dispA = MathUtil.granulize(MathUtil.multiply(dispA, factor), 1.0); 490 dispB = MathUtil.granulize(MathUtil.multiply(dispB, factor), 1.0); 491 } 492 493 /** 494 * {@inheritDoc} 495 */ 496 @Override 497 public void translateCoords(double xFactor, double yFactor) { 498 Point2D factor = new Point2D.Double(xFactor, yFactor); 499 super.setCoordsCenter(MathUtil.add(getCoordsCenter(), factor)); 500 } 501 502 /** 503 * {@inheritDoc} 504 */ 505 @Override 506 public void rotateCoords(double angleDEG) { 507 // rotate coordinates 508 double rotRAD = Math.toRadians(angleDEG); 509 double sineRot = Math.sin(rotRAD); 510 double cosineRot = Math.cos(rotRAD); 511 512 // rotate displacements around origin {0, 0} 513 Point2D center_temp = getCoordsCenter(); 514 super.setCoordsCenter(MathUtil.zeroPoint2D); 515 dispA = rotatePoint(dispA, sineRot, cosineRot); 516 dispB = rotatePoint(dispB, sineRot, cosineRot); 517 super.setCoordsCenter(center_temp); 518 519 } 520 521 /** 522 * {@inheritDoc} 523 */ 524 @Override 525 protected HitPointType findHitPointType(Point2D hitPoint, boolean useRectangles, boolean requireUnconnected) { 526 HitPointType result = HitPointType.NONE; // assume point not on connection 527 //note: optimization here: instead of creating rectangles for all the 528 // points to check below, we create a rectangle for the test point 529 // and test if the points below are in that rectangle instead. 530 Rectangle2D r = trackControlCircleRectAt(hitPoint); 531 Point2D p, minPoint = MathUtil.zeroPoint2D; 532 533 double circleRadius = LayoutEditor.SIZE * layoutEditor.getTurnoutCircleSize(); 534 double distance, minDistance = POSITIVE_INFINITY; 535 536 //check the center point 537 if (!requireUnconnected) { 538 p = getCoordsCenter(); 539 distance = MathUtil.distance(p, hitPoint); 540 if (distance < minDistance) { 541 minDistance = distance; 542 minPoint = p; 543 result = HitPointType.LEVEL_XING_CENTER; 544 } 545 } 546 547 //check the A connection point 548 if (!requireUnconnected || (getConnectA() == null)) { 549 p = getCoordsA(); 550 distance = MathUtil.distance(p, hitPoint); 551 if (distance < minDistance) { 552 minDistance = distance; 553 minPoint = p; 554 result = HitPointType.LEVEL_XING_A; 555 } 556 } 557 558 //check the B connection point 559 if (!requireUnconnected || (getConnectB() == null)) { 560 p = getCoordsB(); 561 distance = MathUtil.distance(p, hitPoint); 562 if (distance < minDistance) { 563 minDistance = distance; 564 minPoint = p; 565 result = HitPointType.LEVEL_XING_B; 566 } 567 } 568 569 //check the C connection point 570 if (!requireUnconnected || (getConnectC() == null)) { 571 p = getCoordsC(); 572 distance = MathUtil.distance(p, hitPoint); 573 if (distance < minDistance) { 574 minDistance = distance; 575 minPoint = p; 576 result = HitPointType.LEVEL_XING_C; 577 } 578 } 579 580 //check the D connection point 581 if (!requireUnconnected || (getConnectD() == null)) { 582 p = getCoordsD(); 583 distance = MathUtil.distance(p, hitPoint); 584 if (distance < minDistance) { 585 minDistance = distance; 586 minPoint = p; 587 result = HitPointType.LEVEL_XING_D; 588 } 589 } 590 if ((useRectangles && !r.contains(minPoint)) 591 || (!useRectangles && (minDistance > circleRadius))) { 592 result = HitPointType.NONE; 593 } 594 return result; 595 } // findHitPointType 596 597 // initialization instance variables (used when loading a LayoutEditor) 598// public String connectAName = ""; 599// public String connectBName = ""; 600// public String connectCName = ""; 601// public String connectDName = ""; 602// 603// public String tLayoutBlockNameAC = ""; 604// public String tLayoutBlockNameBD = ""; 605 606 /** 607 * {@inheritDoc} 608 */ 609 @Override 610 public boolean canRemove() { 611 return xing.canRemove(); 612 } 613 614// * 615// * Build a list of sensors, signal heads, and signal masts attached to a 616// * level crossing point. 617// * 618// * @param pointName Specify the point (A-D) or all (All) points. 619// * @return a list of bean reference names. 620// */ 621// public ArrayList<String> getBeanReferences(String pointName) { 622// ArrayList<String> references = new ArrayList<>(); 623// if (pointName.equals("A") || pointName.equals("All")) { // NOI18N 624// if (!getSignalAMastName().isEmpty()) { 625// references.add(getSignalAMastName()); 626// } 627// if (!getSensorAName().isEmpty()) { 628// references.add(getSensorAName()); 629// } 630// if (!getSignalAName().isEmpty()) { 631// references.add(getSignalAName()); 632// } 633// } 634// if (pointName.equals("B") || pointName.equals("All")) { // NOI18N 635// if (!getSignalBMastName().isEmpty()) { 636// references.add(getSignalBMastName()); 637// } 638// if (!getSensorBName().isEmpty()) { 639// references.add(getSensorBName()); 640// } 641// if (!getSignalBName().isEmpty()) { 642// references.add(getSignalBName()); 643// } 644// } 645// if (pointName.equals("C") || pointName.equals("All")) { // NOI18N 646// if (!getSignalCMastName().isEmpty()) { 647// references.add(getSignalCMastName()); 648// } 649// if (!getSensorCName().isEmpty()) { 650// references.add(getSensorCName()); 651// } 652// if (!getSignalCName().isEmpty()) { 653// references.add(getSignalCName()); 654// } 655// } 656// if (pointName.equals("D") || pointName.equals("All")) { // NOI18N 657// if (!getSignalDMastName().isEmpty()) { 658// references.add(getSignalDMastName()); 659// } 660// if (!getSensorDName().isEmpty()) { 661// references.add(getSensorDName()); 662// } 663// if (!getSignalDName().isEmpty()) { 664// references.add(getSignalDName()); 665// } 666// } 667// return references; 668// } 669 670 JPopupMenu popup = null; 671 672 /** 673 * {@inheritDoc} 674 */ 675 @Override 676 @Nonnull 677 protected JPopupMenu showPopup(@Nonnull JmriMouseEvent mouseEvent) { 678 if (popup != null) { 679 popup.removeAll(); 680 } else { 681 popup = new JPopupMenu(); 682 } 683 if (layoutEditor.isEditable()) { 684 JMenuItem jmi = popup.add(Bundle.getMessage("MakeLabel", Bundle.getMessage("LevelCrossing")) + getName()); 685 jmi.setEnabled(false); 686 687 boolean blockACAssigned = false; 688 boolean blockBDAssigned = false; 689 if (getLayoutBlockAC() == null) { 690 jmi = popup.add(Bundle.getMessage("NoBlockX", "AC")); 691 } else { 692 jmi = popup.add(Bundle.getMessage("MakeLabel", Bundle.getMessage("Block_ID", "AC")) + getLayoutBlockAC().getDisplayName()); 693 blockACAssigned = true; 694 } 695 jmi.setEnabled(false); 696 697 if (getLayoutBlockBD() == null) { 698 jmi = popup.add(Bundle.getMessage("NoBlockX", "BD")); 699 } else { 700 jmi = popup.add(Bundle.getMessage("MakeLabel", Bundle.getMessage("Block_ID", "BD")) + getLayoutBlockBD().getDisplayName()); 701 blockBDAssigned = true; 702 } 703 jmi.setEnabled(false); 704 705 // if there are any track connections 706 if ((getConnectA() != null) || (getConnectB() != null) 707 || (getConnectC() != null) || (getConnectD() != null)) { 708 JMenu connectionsMenu = new JMenu(Bundle.getMessage("Connections")); // there is no pane opening (which is what ... implies) 709 if (getConnectA() != null) { 710 connectionsMenu.add(new AbstractAction(Bundle.getMessage("MakeLabel", "A") + getConnectA().getName()) { 711 @Override 712 public void actionPerformed(ActionEvent e) { 713 LayoutEditorFindItems lf = layoutEditor.getFinder(); 714 LayoutTrack lt = lf.findObjectByName(getConnectA().getName()); 715 // this shouldn't ever be null... however... 716 if (lt != null) { 717 LayoutTrackView ltv = layoutEditor.getLayoutTrackView(lt); 718 layoutEditor.setSelectionRect(ltv.getBounds()); 719 ltv.showPopup(); 720 } 721 } 722 }); 723 } 724 if (getConnectB() != null) { 725 connectionsMenu.add(new AbstractAction(Bundle.getMessage("MakeLabel", "B") + getConnectB().getName()) { 726 @Override 727 public void actionPerformed(ActionEvent e) { 728 LayoutEditorFindItems lf = layoutEditor.getFinder(); 729 LayoutTrack lt = lf.findObjectByName(getConnectB().getName()); 730 // this shouldn't ever be null... however... 731 if (lt != null) { 732 LayoutTrackView ltv = layoutEditor.getLayoutTrackView(lt); 733 layoutEditor.setSelectionRect(ltv.getBounds()); 734 ltv.showPopup(); 735 } 736 } 737 }); 738 } 739 if (getConnectC() != null) { 740 connectionsMenu.add(new AbstractAction(Bundle.getMessage("MakeLabel", "C") + getConnectC().getName()) { 741 @Override 742 public void actionPerformed(ActionEvent e) { 743 LayoutEditorFindItems lf = layoutEditor.getFinder(); 744 LayoutTrack lt = lf.findObjectByName(getConnectC().getName()); 745 // this shouldn't ever be null... however... 746 if (lt != null) { 747 LayoutTrackView ltv = layoutEditor.getLayoutTrackView(lt); 748 layoutEditor.setSelectionRect(ltv.getBounds()); 749 ltv.showPopup(); 750 } 751 } 752 }); 753 } 754 if (getConnectD() != null) { 755 connectionsMenu.add(new AbstractAction(Bundle.getMessage("MakeLabel", "D") + getConnectD().getName()) { 756 @Override 757 public void actionPerformed(ActionEvent e) { 758 LayoutEditorFindItems lf = layoutEditor.getFinder(); 759 LayoutTrack lt = lf.findObjectByName(getConnectD().getName()); 760 // this shouldn't ever be null... however... 761 if (lt != null) { 762 LayoutTrackView ltv = layoutEditor.getLayoutTrackView(lt); 763 layoutEditor.setSelectionRect(ltv.getBounds()); 764 ltv.showPopup(); 765 } 766 } 767 }); 768 } 769 popup.add(connectionsMenu); 770 } 771 772 popup.add(new JSeparator(JSeparator.HORIZONTAL)); 773 774 JCheckBoxMenuItem hiddenCheckBoxMenuItem = new JCheckBoxMenuItem(Bundle.getMessage("Hidden")); 775 hiddenCheckBoxMenuItem.setSelected(isHidden()); 776 popup.add(hiddenCheckBoxMenuItem); 777 hiddenCheckBoxMenuItem.addActionListener((java.awt.event.ActionEvent e3) -> setHidden(hiddenCheckBoxMenuItem.isSelected())); 778 779 popup.add(new AbstractAction(Bundle.getMessage("ButtonEdit")) { 780 @Override 781 public void actionPerformed(ActionEvent e) { 782 editor.editLayoutTrack(LevelXingView.this); 783 } 784 }); 785 popup.add(new AbstractAction(Bundle.getMessage("ButtonDelete")) { 786 @Override 787 public void actionPerformed(ActionEvent e) { 788 if (canRemove() && removeInlineLogixNG() 789 && layoutEditor.removeLevelXing(xing)) { 790 // Returned true if user did not cancel 791 xing.remove(); 792 dispose(); 793 } 794 } 795 }); 796 if (blockACAssigned && blockBDAssigned) { 797 AbstractAction ssaa = new AbstractAction(Bundle.getMessage("SetSignals")) { 798 @Override 799 public void actionPerformed(ActionEvent e) { 800 // bring up signals at level crossing tool dialog 801 LayoutEditorToolBarPanel letbp = getLayoutEditorToolBarPanel(); 802 layoutEditor.getLETools(). 803 setSignalsAtLevelXingFromMenu(xing, 804 letbp.signalIconEditor, 805 letbp.signalFrame); 806 } 807 }; 808 JMenu jm = new JMenu(Bundle.getMessage("SignalHeads")); 809 if (layoutEditor.getLETools(). 810 addLevelXingSignalHeadInfoToMenu(xing, jm)) { 811 jm.add(ssaa); 812 popup.add(jm); 813 } else { 814 popup.add(ssaa); 815 } 816 } 817 818 final String[] boundaryBetween = xing.getBlockBoundaries(); 819 boolean blockBoundaries = false; 820 if (jmri.InstanceManager.getDefault(LayoutBlockManager.class).isAdvancedRoutingEnabled()) { 821 if (blockACAssigned && !blockBDAssigned) { 822 popup.add(new AbstractAction(Bundle.getMessage("ViewBlockRouting")) { 823 @Override 824 public void actionPerformed(ActionEvent e) { 825 AbstractAction routeTableAction = new LayoutBlockRouteTableAction("ViewRouting", getLayoutBlockAC()); 826 routeTableAction.actionPerformed(e); 827 } 828 }); 829 } else if (!blockACAssigned && blockBDAssigned) { 830 popup.add(new AbstractAction(Bundle.getMessage("ViewBlockRouting")) { 831 @Override 832 public void actionPerformed(ActionEvent e) { 833 AbstractAction routeTableAction = new LayoutBlockRouteTableAction("ViewRouting", getLayoutBlockBD()); 834 routeTableAction.actionPerformed(e); 835 } 836 }); 837 } else if (blockACAssigned && blockBDAssigned) { 838 JMenu viewRouting = new JMenu(Bundle.getMessage("ViewBlockRouting")); 839 viewRouting.add(new AbstractAction(getLayoutBlockAC().getDisplayName()) { 840 @Override 841 public void actionPerformed(ActionEvent e) { 842 AbstractAction routeTableAction = new LayoutBlockRouteTableAction(getLayoutBlockAC().getDisplayName(), getLayoutBlockAC()); 843 routeTableAction.actionPerformed(e); 844 } 845 }); 846 847 viewRouting.add(new AbstractAction(getLayoutBlockBD().getDisplayName()) { 848 @Override 849 public void actionPerformed(ActionEvent e) { 850 AbstractAction routeTableAction = new LayoutBlockRouteTableAction(getLayoutBlockBD().getDisplayName(), getLayoutBlockBD()); 851 routeTableAction.actionPerformed(e); 852 } 853 }); 854 855 popup.add(viewRouting); 856 } 857 } 858 859 for (int i = 0; i < 4; i++) { 860 if (boundaryBetween[i] != null) { 861 blockBoundaries = true; 862 } 863 } 864 if (blockBoundaries) { 865 popup.add(new AbstractAction(Bundle.getMessage("SetSignalMasts")) { 866 @Override 867 public void actionPerformed(ActionEvent e) { 868 LayoutEditorToolBarPanel letbp = getLayoutEditorToolBarPanel(); 869 layoutEditor.getLETools(). 870 setSignalMastsAtLevelXingFromMenu( 871 xing, boundaryBetween, 872 letbp.signalFrame); 873 } 874 }); 875 popup.add(new AbstractAction(Bundle.getMessage("SetSensors")) { 876 @Override 877 public void actionPerformed(ActionEvent e) { 878 LayoutEditorToolBarPanel letbp = getLayoutEditorToolBarPanel(); 879 layoutEditor.getLETools().setSensorsAtLevelXingFromMenu( 880 xing, boundaryBetween, 881 letbp.sensorIconEditor, 882 letbp.sensorFrame); 883 } 884 }); 885 } 886 887 layoutEditor.setShowAlignmentMenu(popup); 888 addCommonPopupItems(mouseEvent, popup); 889 popup.show(mouseEvent.getComponent(), mouseEvent.getX(), mouseEvent.getY()); 890 } else if (!viewAdditionalMenu.isEmpty()) { 891 setAdditionalViewPopUpMenu(popup); 892 addCommonPopupItems(mouseEvent, popup); 893 popup.show(mouseEvent.getComponent(), mouseEvent.getX(), mouseEvent.getY()); 894 } 895 return popup; 896 } // showPopup 897 898// public String[] getBlockBoundaries() { 899// final String[] boundaryBetween = new String[4]; 900// 901// String blockNameAC = getBlockNameAC(); 902// String blockNameBD = getBlockNameBD(); 903// 904// LayoutBlock blockAC = getLayoutBlockAC(); 905// LayoutBlock blockBD = getLayoutBlockAC(); 906// 907// if (!blockNameAC.isEmpty() && (blockAC != null)) { 908// if ((connectA instanceof TrackSegment) && (((TrackSegment) connectA).getLayoutBlock() != blockAC)) { 909// try { 910// boundaryBetween[0] = (((TrackSegment) connectA).getLayoutBlock().getDisplayName() + " - " + blockAC.getDisplayName()); 911// } catch (java.lang.NullPointerException e) { 912// //Can be considered normal if tracksegement hasn't yet been allocated a block 913// log.debug("TrackSegement at connection A doesn't contain a layout block"); 914// } 915// } 916// if ((connectC instanceof TrackSegment) && (((TrackSegment) connectC).getLayoutBlock() != blockAC)) { 917// try { 918// boundaryBetween[2] = (((TrackSegment) connectC).getLayoutBlock().getDisplayName() + " - " + blockAC.getDisplayName()); 919// } catch (java.lang.NullPointerException e) { 920// //Can be considered normal if tracksegement hasn't yet been allocated a block 921// log.debug("TrackSegement at connection C doesn't contain a layout block"); 922// } 923// } 924// } 925// if (!blockNameBD.isEmpty() && (blockBD != null)) { 926// if ((connectB instanceof TrackSegment) && (((TrackSegment) connectB).getLayoutBlock() != blockBD)) { 927// try { 928// boundaryBetween[1] = (((TrackSegment) connectB).getLayoutBlock().getDisplayName() + " - " + blockBD.getDisplayName()); 929// } catch (java.lang.NullPointerException e) { 930// //Can be considered normal if tracksegement hasn't yet been allocated a block 931// log.debug("TrackSegement at connection B doesn't contain a layout block"); 932// } 933// } 934// if ((connectD instanceof TrackSegment) && (((TrackSegment) connectD).getLayoutBlock() != blockBD)) { 935// try { 936// boundaryBetween[3] = (((TrackSegment) connectD).getLayoutBlock().getDisplayName() + " - " + blockBD.getDisplayName()); 937// } catch (java.lang.NullPointerException e) { 938// //Can be considered normal if tracksegement hasn't yet been allocated a block 939// log.debug("TrackSegement at connection D doesn't contain a layout block"); 940// } 941// } 942// } 943// return boundaryBetween; 944// } 945 946 /** 947 * Clean up when this object is no longer needed. Should not be called while 948 * the object is still displayed; see remove(). 949 */ 950 public void dispose() { 951 if (popup != null) { 952 popup.removeAll(); 953 } 954 popup = null; 955 } 956 957 /** 958 * Remove this object from display and persistance. 959 */ 960// public void remove() { 961// // remove from persistance by flagging inactive 962// active = false; 963// } 964// 965// boolean active = true; 966// 967// * 968// * "active" means that the object is still displayed, and should be stored. 969// */ 970// public boolean isActive() { 971// return active; 972// } 973 974// ArrayList<SignalMast> sml = new ArrayList<>(); 975// 976// public void addSignalMastLogic(SignalMast sm) { 977// if (sml.contains(sm)) { 978// return; 979// } 980// if (sml.isEmpty()) { 981// sml.add(sm); 982// return; 983// } 984// SignalMastLogic sl = InstanceManager.getDefault(jmri.SignalMastLogicManager.class).getSignalMastLogic(sm); 985// for (SignalMast signalMast : sml) { 986// SignalMastLogic s = InstanceManager.getDefault(SignalMastLogicManager.class).getSignalMastLogic(signalMast); 987// if (s != null) { 988// s.setConflictingLogic(sm, xing); 989// } 990// sl.setConflictingLogic(signalMast, xing); 991// } 992// sml.add(sm); 993// } 994// 995// public void removeSignalMastLogic(SignalMast sm) { 996// if (!sml.contains(sm)) { 997// return; 998// } 999// sml.remove(sm); 1000// if (sml.isEmpty()) { 1001// return; 1002// } 1003// for (int i = 0; i < sml.size(); i++) { 1004// SignalMastLogic s = InstanceManager.getDefault(jmri.SignalMastLogicManager.class).getSignalMastLogic(sm); 1005// if (s != null) { 1006// s.removeConflictingLogic(sm, xing); 1007// } 1008// } 1009// } 1010 1011 ArrayList<JMenuItem> editAdditionalMenu = new ArrayList<>(0); 1012 ArrayList<JMenuItem> viewAdditionalMenu = new ArrayList<>(0); 1013 1014 public void addEditPopUpMenu(JMenuItem menu) { 1015 if (!editAdditionalMenu.contains(menu)) { 1016 editAdditionalMenu.add(menu); 1017 } 1018 } 1019 1020 public void addViewPopUpMenu(JMenuItem menu) { 1021 if (!viewAdditionalMenu.contains(menu)) { 1022 viewAdditionalMenu.add(menu); 1023 } 1024 } 1025 1026 public void setAdditionalEditPopUpMenu(JPopupMenu popup) { 1027 if (editAdditionalMenu.isEmpty()) { 1028 return; 1029 } 1030 popup.addSeparator(); 1031 for (JMenuItem mi : editAdditionalMenu) { 1032 popup.add(mi); 1033 } 1034 } 1035 1036 public void setAdditionalViewPopUpMenu(JPopupMenu popup) { 1037 if (viewAdditionalMenu.isEmpty()) { 1038 return; 1039 } 1040 popup.addSeparator(); 1041 for (JMenuItem mi : viewAdditionalMenu) { 1042 popup.add(mi); 1043 } 1044 } 1045 1046 /** 1047 * Draw track decorations. 1048 * 1049 * This type of track has none, so this method is empty. 1050 */ 1051 @Override 1052 protected void drawDecorations(Graphics2D g2) {} 1053 1054 /** 1055 * Draw this level crossing. 1056 * 1057 * @param g2 the graphics port to draw to 1058 */ 1059 @Override 1060 protected void draw1(Graphics2D g2, boolean isMain, boolean isBlock) { 1061 if (isMain == isMainlineAC()) { 1062 if (isBlock) { 1063 setColorForTrackBlock(g2, getLayoutBlockAC()); 1064 } 1065 g2.draw(new Line2D.Double(getCoordsA(), getCoordsC())); 1066 } 1067 if (isMain == isMainlineBD()) { 1068 if (isBlock) { 1069 setColorForTrackBlock(g2, getLayoutBlockBD()); 1070 } 1071 g2.draw(new Line2D.Double(getCoordsB(), getCoordsD())); 1072 } 1073 } 1074 1075 /** 1076 * {@inheritDoc} 1077 */ 1078 @Override 1079 protected void draw2(Graphics2D g2, boolean isMain, float railDisplacement) { 1080 Point2D pA = getCoordsA(); 1081 Point2D pB = getCoordsB(); 1082 Point2D pC = getCoordsC(); 1083 Point2D pD = getCoordsD(); 1084 Point2D pM = getCoordsCenter(); 1085 1086 Point2D vAC = MathUtil.normalize(MathUtil.subtract(pC, pA), railDisplacement); 1087 double dirAC_DEG = MathUtil.computeAngleDEG(pA, pC); 1088 Point2D vACo = MathUtil.orthogonal(vAC); 1089 Point2D pAL = MathUtil.subtract(pA, vACo); 1090 Point2D pAR = MathUtil.add(pA, vACo); 1091 Point2D pCL = MathUtil.subtract(pC, vACo); 1092 Point2D pCR = MathUtil.add(pC, vACo); 1093 1094 Point2D vBD = MathUtil.normalize(MathUtil.subtract(pD, pB), railDisplacement); 1095 double dirBD_DEG = MathUtil.computeAngleDEG(pB, pD); 1096 Point2D vBDo = MathUtil.orthogonal(vBD); 1097 Point2D pBL = MathUtil.subtract(pB, vBDo); 1098 Point2D pBR = MathUtil.add(pB, vBDo); 1099 Point2D pDL = MathUtil.subtract(pD, vBDo); 1100 Point2D pDR = MathUtil.add(pD, vBDo); 1101 1102 double deltaDEG = MathUtil.absDiffAngleDEG(dirAC_DEG, dirBD_DEG); 1103 double deltaRAD = Math.toRadians(deltaDEG); 1104 1105 double hypotK = railDisplacement / Math.cos((PI - deltaRAD) / 2.0); 1106 double hypotV = railDisplacement / Math.cos(deltaRAD / 2.0); 1107 1108 log.debug("dir AC: {}, BD: {}, diff: {}", dirAC_DEG, dirBD_DEG, deltaDEG); 1109 1110 Point2D vDisK = MathUtil.normalize(MathUtil.add(vAC, vBD), hypotK); 1111 Point2D vDisV = MathUtil.normalize(MathUtil.orthogonal(vDisK), hypotV); 1112 Point2D pKL = MathUtil.subtract(pM, vDisK); 1113 Point2D pKR = MathUtil.add(pM, vDisK); 1114 Point2D pVL = MathUtil.subtract(pM, vDisV); 1115 Point2D pVR = MathUtil.add(pM, vDisV); 1116 1117 if (isMain == isMainlineAC()) { 1118 // this is the *2.0 vector (rail gap) for the AC diamond parts 1119 Point2D vAC2 = MathUtil.normalize(vAC, 2.0); 1120 // KL toward C, VR toward A, VL toward C and KR toward A 1121 Point2D pKLtC = MathUtil.add(pKL, vAC2); 1122 Point2D pVRtA = MathUtil.subtract(pVR, vAC2); 1123 Point2D pVLtC = MathUtil.add(pVL, vAC2); 1124 Point2D pKRtA = MathUtil.subtract(pKR, vAC2); 1125 1126 // draw right AC rail: AR====KL == VR====CR 1127 g2.draw(new Line2D.Double(pAR, pKL)); 1128 g2.draw(new Line2D.Double(pKLtC, pVRtA)); 1129 g2.draw(new Line2D.Double(pVR, pCR)); 1130 1131 // draw left AC rail: AL====VL == KR====CL 1132 g2.draw(new Line2D.Double(pAL, pVL)); 1133 g2.draw(new Line2D.Double(pVLtC, pKRtA)); 1134 g2.draw(new Line2D.Double(pKR, pCL)); 1135 } 1136 if (isMain == isMainlineBD()) { 1137 // this is the *2.0 vector (rail gap) for the BD diamond parts 1138 Point2D vBD2 = MathUtil.normalize(vBD, 2.0); 1139 // VR toward D, KR toward B, KL toward D and VL toward B 1140 Point2D pVRtD = MathUtil.add(pVR, vBD2); 1141 Point2D pKRtB = MathUtil.subtract(pKR, vBD2); 1142 Point2D pKLtD = MathUtil.add(pKL, vBD2); 1143 Point2D pVLtB = MathUtil.subtract(pVL, vBD2); 1144 1145 // draw right BD rail: BR====VR == KR====DR 1146 g2.draw(new Line2D.Double(pBR, pVR)); 1147 g2.draw(new Line2D.Double(pVRtD, pKRtB)); 1148 g2.draw(new Line2D.Double(pKR, pDR)); 1149 1150 // draw left BD rail: BL====KL == VL====DL 1151 g2.draw(new Line2D.Double(pBL, pKL)); 1152 g2.draw(new Line2D.Double(pKLtD, pVLtB)); 1153 g2.draw(new Line2D.Double(pVL, pDL)); 1154 } 1155 } 1156 1157 /** 1158 * {@inheritDoc} 1159 */ 1160 @Override 1161 protected void highlightUnconnected(Graphics2D g2, HitPointType specificType) { 1162 if (((specificType == HitPointType.NONE) || (specificType == HitPointType.LEVEL_XING_A)) 1163 && (getConnectA() == null)) { 1164 g2.fill(trackControlCircleAt(getCoordsA())); 1165 } 1166 1167 if (((specificType == HitPointType.NONE) || (specificType == HitPointType.LEVEL_XING_B)) 1168 && (getConnectB() == null)) { 1169 g2.fill(trackControlCircleAt(getCoordsB())); 1170 } 1171 1172 if (((specificType == HitPointType.NONE) || (specificType == HitPointType.LEVEL_XING_C)) 1173 && (getConnectC() == null)) { 1174 g2.fill(trackControlCircleAt(getCoordsC())); 1175 } 1176 1177 if (((specificType == HitPointType.NONE) || (specificType == HitPointType.LEVEL_XING_D)) 1178 && (getConnectD() == null)) { 1179 g2.fill(trackControlCircleAt(getCoordsD())); 1180 } 1181 } 1182 1183 @Override 1184 protected void drawEditControls(Graphics2D g2) { 1185 g2.setColor(layoutEditor.getDefaultTrackColorColor()); 1186 g2.draw(trackEditControlCircleAt(getCoordsCenter())); 1187 1188 if (getConnectA() == null) { 1189 g2.setColor(Color.magenta); 1190 } else { 1191 g2.setColor(Color.blue); 1192 } 1193 g2.draw(layoutEditor.layoutEditorControlRectAt(getCoordsA())); 1194 1195 if (getConnectB() == null) { 1196 g2.setColor(Color.red); 1197 } else { 1198 g2.setColor(Color.green); 1199 } 1200 g2.draw(layoutEditor.layoutEditorControlRectAt(getCoordsB())); 1201 1202 if (getConnectC() == null) { 1203 g2.setColor(Color.red); 1204 } else { 1205 g2.setColor(Color.green); 1206 } 1207 g2.draw(layoutEditor.layoutEditorControlRectAt(getCoordsC())); 1208 1209 if (getConnectD() == null) { 1210 g2.setColor(Color.red); 1211 } else { 1212 g2.setColor(Color.green); 1213 } 1214 g2.draw(layoutEditor.layoutEditorControlRectAt(getCoordsD())); 1215 } 1216 1217 @Override 1218 protected void drawTurnoutControls(Graphics2D g2) { 1219 // LevelXings don't have turnout controls... 1220 // nothing to see here... move along... 1221 } 1222 1223 /* 1224 * {@inheritDoc} 1225 */ 1226 @Override 1227 public void reCheckBlockBoundary() { 1228 // nothing to see here... move along... 1229 } 1230 1231 /* 1232 * {@inheritDoc} temporary 1233 */ 1234 @Override 1235 protected ArrayList<LayoutConnectivity> getLayoutConnectivity() { 1236 // nothing to see here... move along... 1237 return null; 1238 } 1239 1240 /** 1241 * {@inheritDoc} 1242 */ 1243 @Override 1244 public List<HitPointType> checkForFreeConnections() { 1245 throw new IllegalArgumentException("should have called Object instead of view temporary"); 1246// List<HitPointType> result = new ArrayList<>(); 1247// 1248// //check the A connection point 1249// if (getConnectA() == null) { 1250// result.add(HitPointType.LEVEL_XING_A); 1251// } 1252// 1253// //check the B connection point 1254// if (getConnectB() == null) { 1255// result.add(HitPointType.LEVEL_XING_B); 1256// } 1257// 1258// //check the C connection point 1259// if (getConnectC() == null) { 1260// result.add(HitPointType.LEVEL_XING_C); 1261// } 1262// 1263// //check the D connection point 1264// if (getConnectD() == null) { 1265// result.add(HitPointType.LEVEL_XING_D); 1266// } 1267// return result; 1268 } 1269 1270 /** 1271 * {@inheritDoc} 1272 */ 1273 @Override 1274 public boolean checkForUnAssignedBlocks() { 1275// return ((getLayoutBlockAC() != null) && (getLayoutBlockBD() != null)); 1276 throw new IllegalArgumentException("should have called Object instead of View temporary"); 1277 } 1278 1279 /** 1280 * {@inheritDoc} 1281 */ 1282 @Override 1283 public void checkForNonContiguousBlocks( 1284 @Nonnull HashMap<String, List<Set<String>>> blockNamesToTrackNameSetsMap) { 1285 throw new IllegalArgumentException("should have called Object instead of View temporary"); 1286 1287 /* 1288 * For each (non-null) blocks of this track do: 1289 * #1) If it's got an entry in the blockNamesToTrackNameSetMap then 1290 * #2) If this track is already in the TrackNameSet for this block 1291 * then return (done!) 1292 * #3) else add a new set (with this block/track) to 1293 * blockNamesToTrackNameSetMap and check all the connections in this 1294 * block (by calling the 2nd method below) 1295 * <p> 1296 * Basically, we're maintaining contiguous track sets for each block found 1297 * (in blockNamesToTrackNameSetMap) 1298 */ 1299 1300 // We're only using a map here because it's convient to 1301 // use it to pair up blocks and connections 1302// Map<LayoutTrack, String> blocksAndTracksMap = new HashMap<>(); 1303// if ((getLayoutBlockAC() != null) && (connectA != null)) { 1304// blocksAndTracksMap.put(connectA, getLayoutBlockAC().getDisplayName()); 1305// } 1306// if ((getLayoutBlockAC() != null) && (connectC != null)) { 1307// blocksAndTracksMap.put(connectC, getLayoutBlockAC().getDisplayName()); 1308// } 1309// if ((getLayoutBlockBD() != null) && (connectB != null)) { 1310// blocksAndTracksMap.put(connectB, getLayoutBlockBD().getDisplayName()); 1311// } 1312// if ((getLayoutBlockBD() != null) && (connectD != null)) { 1313// blocksAndTracksMap.put(connectD, getLayoutBlockBD().getDisplayName()); 1314// } 1315// 1316// List<Set<String>> TrackNameSets = null; 1317// Set<String> TrackNameSet = null; 1318// for (Map.Entry<LayoutTrack, String> entry : blocksAndTracksMap.entrySet()) { 1319// LayoutTrack theConnect = entry.getKey(); 1320// String theBlockName = entry.getValue(); 1321// 1322// TrackNameSet = null; // assume not found (pessimist!) 1323// TrackNameSets = blockNamesToTrackNameSetsMap.get(theBlockName); 1324// if (TrackNameSets != null) { // (#1) 1325// for (Set<String> checkTrackNameSet : TrackNameSets) { 1326// if (checkTrackNameSet.contains(getName())) { // (#2) 1327// TrackNameSet = checkTrackNameSet; 1328// break; 1329// } 1330// } 1331// } else { // (#3) 1332// log.debug("*New block ('{}') trackNameSets", theBlockName); 1333// TrackNameSets = new ArrayList<>(); 1334// blockNamesToTrackNameSetsMap.put(theBlockName, TrackNameSets); 1335// } 1336// if (TrackNameSet == null) { 1337// TrackNameSet = new LinkedHashSet<>(); 1338// TrackNameSets.add(TrackNameSet); 1339// } 1340// if (TrackNameSet.add(getName())) { 1341// log.debug("* Add track ''{}'' to trackNameSet for block ''{}''", getName(), theBlockName); 1342// } 1343// theConnect.collectContiguousTracksNamesInBlockNamed(theBlockName, TrackNameSet); 1344// } 1345 } // collectContiguousTracksNamesInBlockNamed 1346 1347 /** 1348 * {@inheritDoc} 1349 */ 1350 @Override 1351 public void collectContiguousTracksNamesInBlockNamed(@Nonnull String blockName, 1352 @Nonnull Set<String> TrackNameSet) { 1353 throw new IllegalArgumentException("should have called Object instead of View temporary"); 1354// if (!TrackNameSet.contains(getName())) { 1355// // check all the matching blocks in this track and... 1356// // #1) add us to TrackNameSet and... 1357// // #2) flood them 1358// //check the AC blockName 1359// if (getBlockNameAC().equals(blockName)) { 1360// // if we are added to the TrackNameSet 1361// if (TrackNameSet.add(getName())) { 1362// log.debug("* Add track ''{}'for block ''{}''", getName(), blockName); 1363// } 1364// // it's time to play... flood your neighbours! 1365// if (connectA != null) { 1366// connectA.collectContiguousTracksNamesInBlockNamed(blockName, TrackNameSet); 1367// } 1368// if (connectC != null) { 1369// connectC.collectContiguousTracksNamesInBlockNamed(blockName, TrackNameSet); 1370// } 1371// } 1372// //check the BD blockName 1373// if (getBlockNameBD().equals(blockName)) { 1374// // if we are added to the TrackNameSet 1375// if (TrackNameSet.add(getName())) { 1376// log.debug("* Add track ''{}''for block ''{}''", getName(), blockName); 1377// } 1378// // it's time to play... flood your neighbours! 1379// if (connectB != null) { 1380// connectB.collectContiguousTracksNamesInBlockNamed(blockName, TrackNameSet); 1381// } 1382// if (connectD != null) { 1383// connectD.collectContiguousTracksNamesInBlockNamed(blockName, TrackNameSet); 1384// } 1385// } 1386// } 1387 } 1388 1389 /** 1390 * {@inheritDoc} 1391 */ 1392 @Override 1393 public void setAllLayoutBlocks(LayoutBlock layoutBlock) { 1394 throw new IllegalArgumentException("should have called Object instead of View temporary"); 1395// setLayoutBlockAC(layoutBlock); 1396// setLayoutBlockBD(layoutBlock); 1397 } 1398 1399 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LevelXingView.class); 1400}