001package jmri.jmrit.display.layoutEditor;
002
003import java.util.List;
004import java.util.stream.Stream;
005
006import javax.annotation.Nonnull;
007
008/**
009 * This interface serves as a manager for the overall layout model via
010 * collections of i.e. LayoutTurnout, LayoutBlock,
011 * PositionablePoint, Track Segment, LayoutSlip and LevelXing objects
012 * along with their corresponding *View objects.
013 * (Having *View objects here, which are specific to a panel, may
014 * only be here as a temporary measure)
015 * <p>
016 * Provides a temporary setDirty()/isDirty() and redrawPanel() mechanism
017 * for marking changes. That may have to grow and/or change. For
018 * example, redrawPanel()  (which could be renamed) might fire listeners to cause repaints.
019 * 
020 *
021 * @see LayoutEditorFindItems
022 * @see LayoutEditorAuxTools
023 *
024 * @author Bob Jacobsen Copyright: (c) 2020
025 */
026public interface LayoutModels {
027
028    /**
029     * Check the dirty state
030     *
031     * @return true if contents of models have changed,
032     */
033    public boolean isDirty();
034
035    public void setDirty();
036
037    /**
038     * A change has happen that might not need to be stored,
039     * but should cause the presentation to be updated.
040     */
041    public void redrawPanel();
042
043    // ====================================
044    // Access to related navigation objects
045    // ====================================
046
047    @Nonnull
048    public LayoutEditorAuxTools getLEAuxTools();
049        
050
051    // ====================================
052    // Access to (lists of) model objects
053    // ====================================
054
055    //
056    // General access. (temporary) Is this actually preferred to all those specific ones?
057    //
058
059    @Nonnull
060    Stream<LayoutTrack> getLayoutTracksOfClass(Class<? extends LayoutTrack> layoutTrackClass);
061
062    //
063    // General access. (temporary) Is this actually preferred to all those specific ones?
064    //
065    
066    @Nonnull
067    Stream<LayoutTrackView> getLayoutTrackViewsOfClass(Class<? extends LayoutTrackView> layoutTrackViewClass);
068    
069    @Nonnull
070    List<PositionablePointView> getPositionablePointViews();
071
072    @Nonnull
073    List<PositionablePoint> getPositionablePoints();
074
075    @Nonnull
076    List<LayoutSlip> getLayoutSlips();
077
078    @Nonnull
079    List<TrackSegmentView> getTrackSegmentViews();
080
081    @Nonnull
082    List<TrackSegment> getTrackSegments();
083
084    @Nonnull
085    List<LayoutTurnout> getLayoutTurnouts();
086
087    @Nonnull
088    List<LayoutTurntable> getLayoutTurntables();
089
090    @Nonnull
091    List<LevelXing> getLevelXings();
092
093    @Nonnull
094    List<LevelXingView> getLevelXingViews();
095
096    /**
097     * Read-only access to the list of LayoutTrack family objects.
098     * The returned list will throw UnsupportedOperationException
099     * if you attempt to modify it.
100     * @return unmodifiable copy of layout track list.
101     */
102    @Nonnull
103    List<LayoutTrack> getLayoutTracks();
104
105    /**
106     * Read-only access to the list of LayoutTrackView family objects.
107     * The returned list will throw UnsupportedOperationException
108     * if you attempt to modify it.
109     * @return unmodifiable copy of track views.
110     */
111    @Nonnull
112    List<LayoutTrackView> getLayoutTrackViews();
113
114    // temporary
115    LayoutTrackView getLayoutTrackView(LayoutTrack trk);
116    
117    // temporary
118    LevelXingView getLevelXingView(LevelXing xing);
119    
120    // temporary
121    LayoutTurnoutView getLayoutTurnoutView(LayoutTurnout to);
122    
123    // temporary
124    LayoutTurntableView getLayoutTurntableView(LayoutTurntable to);
125        
126    // temporary
127    TrackSegmentView getTrackSegmentView(TrackSegment to);
128
129    // temporary
130    PositionablePointView getPositionablePointView(PositionablePoint to);
131        
132    /**
133     * Add a LayoutTrack and LayoutTrackView to the list of 
134     * LayoutTrack family objects.
135     * @param trk to be stored
136     * @param v corresponding view
137     */
138    void addLayoutTrack(@Nonnull LayoutTrack trk, @Nonnull LayoutTrackView v);
139
140    /**
141     * If item present, delete from the list of LayoutTracks
142     * and force a dirty redraw.
143     * @param trk the layout track to remove.
144     */
145    void removeLayoutTrack(@Nonnull LayoutTrack trk);
146    
147    @Nonnull
148    List<LayoutTurnout> getLayoutTurnoutsAndSlips();
149
150    @Nonnull
151    List<LayoutShape> getLayoutShapes();
152
153    /**
154     * Compute octagonal direction of vector from p1 to p2.
155     * <p>
156     * The octagonal (8) directions are: North, North-East, East,
157     * South-East, South, South-West, West and North-West; see
158     * {@link jmri.Path} for more on this.
159     *
160     * <p>
161     * This method must eventually be in terms _other_ than
162     * the screen geometry of the associated LayoutTrackView objects, 
163     * as it's meant to be the track connectivity direction not the
164     * on the screen implementation.
165     *
166     * @param trk1 track at "from" end
167     * @param h1 the hit point for "from" end
168     * @param trk2 the track at the "to" end
169     * @param h2 the hit at the "to" end
170     * @return the octagonal direction from p1 to p2
171     */
172    public int computeDirection(@Nonnull LayoutTrack trk1, @Nonnull HitPointType h1, 
173                                @Nonnull LayoutTrack trk2, @Nonnull HitPointType h2);
174
175    public int computeDirectionToCenter( @Nonnull LayoutTrack trk1, @Nonnull HitPointType h1, @Nonnull PositionablePoint p);
176    
177    public int computeDirectionFromCenter( @Nonnull PositionablePoint p, @Nonnull LayoutTrack trk1, @Nonnull HitPointType h1);
178
179    default public int computeDirectionAB( @Nonnull LayoutTurnout track) {
180        LayoutTurnoutView tv = getLayoutTurnoutView(track);
181        return jmri.Path.computeDirection(tv.getCoordsA(), tv.getCoordsB());
182    }
183
184    default public int computeDirectionAC( @Nonnull LayoutTurnout track) {
185        LayoutTurnoutView tv = getLayoutTurnoutView(track);
186        return jmri.Path.computeDirection(tv.getCoordsA(), tv.getCoordsC());
187    }
188
189    default public int computeDirectionAD( @Nonnull LayoutTurnout track) {
190        LayoutTurnoutView tv = getLayoutTurnoutView(track);
191        return jmri.Path.computeDirection(tv.getCoordsA(), tv.getCoordsD());
192    }
193
194    default public int computeDirectionBC( @Nonnull LayoutTurnout track) {
195        LayoutTurnoutView tv = getLayoutTurnoutView(track);
196        return jmri.Path.computeDirection(tv.getCoordsB(), tv.getCoordsC());
197    }
198
199    default public int computeDirectionBD( @Nonnull LayoutTurnout track) {
200        LayoutTurnoutView tv = getLayoutTurnoutView(track);
201        return jmri.Path.computeDirection(tv.getCoordsB(), tv.getCoordsD());
202    }
203
204    default public int computeDirectionCD( @Nonnull LayoutTurnout track) {
205        LayoutTurnoutView tv = getLayoutTurnoutView(track);
206        return jmri.Path.computeDirection(tv.getCoordsC(), tv.getCoordsD());
207    }
208
209    /**
210     * Invoked to display a warning about removal.
211     * Lists the attached items that prevent removing the layout track item.
212     * <p>
213     * The default implementation refers this to a View object for displaying a Dialog.
214     *
215     * @param track The involved track
216     * @param itemList A list of the attached heads, masts and/or sensors.
217     * @param typeKey  The object type such as Turnout, Level Crossing, etc.
218     */
219    default public void displayRemoveWarning(LayoutTrack track, List<String> itemList, String typeKey) {
220        getLayoutTrackView(track).displayRemoveWarningDialog(itemList, typeKey);
221    }
222
223
224}