001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.layer;
003
004import java.awt.Graphics2D;
005
006import org.openstreetmap.josm.data.Bounds;
007import org.openstreetmap.josm.gui.MapView;
008
009/**
010 * This is a component that can be painted on the map view.
011 * <p>
012 * You might want to extend {@link AbstractMapViewPaintable} to ease implementation of this.
013 * <p>
014 * That class allows you to listen to paintable change events. Those methods may be moved here some time in the future.
015 * @since   608 (creation)
016 * @since 10600 (functional interface)
017 */
018@FunctionalInterface
019public interface MapViewPaintable {
020
021    /**
022     * This event is fired whenever the paintable got invalidated and needs repainting some time in the future.
023     * <p>
024     * Note: We might add an area in the future.
025     *
026     * @author Michael Zangl
027     */
028    class PaintableInvalidationEvent {
029        private final MapViewPaintable paintable;
030
031        /**
032         * Creates a new {@link PaintableInvalidationEvent}
033         * @param paintable The paintable that is invalidated.
034         */
035        public PaintableInvalidationEvent(MapViewPaintable paintable) {
036            this.paintable = paintable;
037        }
038
039        /**
040         * Gets the layer that was invalidated.
041         * @return The layer.
042         */
043        public MapViewPaintable getLayer() {
044            return paintable;
045        }
046
047        @Override
048        public String toString() {
049            return "LayerInvalidationEvent [layer=" + paintable + ']';
050        }
051    }
052
053    /**
054     * This is a listener that listens to {@link PaintableInvalidationEvent}s
055     * @author Michael Zangl
056     * @since 10600 (functional interface)
057     */
058    @FunctionalInterface
059    interface PaintableInvalidationListener {
060        /**
061         * Called whenever a {@link PaintableInvalidationEvent} is fired. This might be called from any thread.
062         * @param event The event
063         * @since 10600 (renamed)
064         */
065        void paintableInvalidated(PaintableInvalidationEvent event);
066    }
067
068    /**
069     * Gets a new LayerPainter that paints this {@link MapViewPaintable} to the given map view.
070     *
071     * @author Michael Zangl
072     * @since 10458
073     */
074    interface LayerPainter {
075
076        /**
077         * Paints the given layer.
078         * <p>
079         * This can be called in any thread at any time. You will not receive parallel calls for the same map view but you can receive parallel
080         * calls if you use the same {@link LayerPainter} for different map views.
081         * @param graphics The graphics object of the map view you should use.
082         *                 It provides you with a content pane, the bounds and the view state.
083         */
084        void paint(MapViewGraphics graphics);
085
086        /**
087         * Called when the layer is removed from the map view and this painter is not used any more.
088         * <p>
089         * This method is called once on the painter returned by {@link Layer#attachToMapView}
090         * @param event The event.
091         */
092        void detachFromMapView(MapViewEvent event);
093    }
094
095    /**
096     * A event that is fired whenever the map view is attached or detached from any layer.
097     * @author Michael Zangl
098     * @see Layer#attachToMapView
099     * @since 10458
100     */
101    class MapViewEvent {
102        private final MapView mapView;
103        private final boolean temporaryLayer;
104
105        /**
106         * Create a new {@link MapViewEvent}
107         * @param mapView The map view
108         * @param temporaryLayer <code>true</code> if this layer is in the temporary layer list of the view.
109         */
110        public MapViewEvent(MapView mapView, boolean temporaryLayer) {
111            super();
112            this.mapView = mapView;
113            this.temporaryLayer = temporaryLayer;
114        }
115
116        /**
117         * Gets the map view.
118         * @return The map view.
119         */
120        public MapView getMapView() {
121            return mapView;
122        }
123
124        /**
125         * @return true if this {@link MapViewPaintable} is used as a temporary layer.
126         */
127        public boolean isTemporaryLayer() {
128            return temporaryLayer;
129        }
130
131        @Override
132        public String toString() {
133            return "AttachToMapViewEvent [mapView=" + mapView + ", temporaryLayer=" + temporaryLayer + "]";
134        }
135    }
136
137    /**
138     * Paint the dataset using the engine set.
139     * @param g Graphics
140     * @param mv The object that can translate GeoPoints to screen coordinates.
141     * @param bbox Bounding box
142     */
143    void paint(Graphics2D g, MapView mv, Bounds bbox);
144
145    /**
146     * Adds a new paintable invalidation listener.
147     * @param l The listener to add.
148     * @since 12107
149     */
150    default void addInvalidationListener(PaintableInvalidationListener l) {
151    }
152
153    /**
154     * Removes an added paintable invalidation listener. May throw an exception if the listener is added twice.
155     * @param l The listener to remove.
156     * @since 12107
157     */
158    default void removeInvalidationListener(PaintableInvalidationListener l) {
159    }
160
161}