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}