/* * Geotoolkit - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2008 - 2010, Geomatys * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotoolkit.map; import java.beans.PropertyChangeEvent; import java.util.Collections; import java.util.EventObject; import java.util.List; import org.geotoolkit.style.MutableFeatureTypeStyle; import org.geotoolkit.style.MutableStyle; import org.geotoolkit.style.StyleConstants; import org.geotoolkit.style.StyleListener; import static org.apache.sis.util.ArgumentChecks.*; import org.geotoolkit.util.collection.CheckedArrayList; import org.geotoolkit.util.collection.CollectionChangeEvent; import org.opengis.display.primitive.Graphic; /** * Abstract implementation of the MapLayer. * * @author Johann Sorel (Geomatys) * @module */ public abstract class AbstractMapLayer extends AbstractMapItem implements MapLayer,StyleListener { private final List<GraphicBuilder> builders = new CheckedArrayList<GraphicBuilder>(GraphicBuilder.class); private final StyleListener.Weak styleListener = new StyleListener.Weak(null,this); protected MutableStyle style; protected MutableStyle selectionStyle; protected ElevationModel elevation = null; protected boolean selectable = false; private double opacity = 1d; /** * Constructor that can used by subclass only. */ protected AbstractMapLayer(final MutableStyle style){ setStyle(style); this.desc = StyleConstants.DEFAULT_DESCRIPTION; this.selectionStyle = null; } /** * {@inheritDoc } */ @Override public final boolean isWellKnownedType() { return this instanceof FeatureMapLayer || this instanceof CoverageMapLayer; } @Override public List<MapItem> items() { return Collections.EMPTY_LIST; } /** * Getter for property style. * * @return Value of property style. */ @Override public MutableStyle getStyle() { return this.style; } /** * Setter for property style. * * @param style : New value of property style. */ @Override public void setStyle(final MutableStyle style) { ensureNonNull("style", style); final MutableStyle oldStyle; synchronized (this) { oldStyle = this.style; if(style.equals(oldStyle)){ return; } if(oldStyle != null){ styleListener.unregisterSource(oldStyle); } this.style = style; styleListener.registerSource(style); } firePropertyChange(STYLE_PROPERTY, oldStyle, this.style); } @Override public MutableStyle getSelectionStyle(){ return selectionStyle; } @Override public void setSelectionStyle(final MutableStyle style){ final MutableStyle oldStyle; synchronized (this) { oldStyle = this.selectionStyle; if(oldStyle == style){ return; } this.selectionStyle = style; } firePropertyChange(SELECTION_STYLE_PROPERTY, oldStyle, this.selectionStyle); } /** * {@inheritDoc } */ @Override public double getOpacity(){ return opacity; } /** * {@inheritDoc } */ @Override public void setOpacity(final double opacity){ final double oldOpacity; synchronized (this) { oldOpacity = this.opacity; if(oldOpacity == opacity){ return; } this.opacity = opacity; } firePropertyChange(OPACITY_PROPERTY, oldOpacity, this.opacity); } /** * Getter for property selectable. * * @return Value of property selectable. */ @Override public boolean isSelectable() { return this.selectable; } /** * Setter for property selectable. * * @param selectable : New value of property selectable. */ @Override public void setSelectable(final boolean selectable) { final boolean oldSelectable; synchronized (this) { oldSelectable = this.selectable; if(oldSelectable == selectable){ return; } this.selectable = selectable; } firePropertyChange(SELECTABLE_PROPERTY, oldSelectable, this.selectable); } /** * {@inheritDoc } */ @Override public ElevationModel getElevationModel(){ return elevation; } /** * {@inheritDoc } */ @Override public void setElevationModel(final ElevationModel model){ final ElevationModel oldElevation; synchronized (this) { oldElevation = this.elevation; if(oldElevation != null && oldElevation.equals(model)){ return; } this.elevation = model; } firePropertyChange(ELEVATION_PROPERTY, oldElevation, this.elevation); } /** * {@inheritDoc } */ @Override public List<GraphicBuilder> graphicBuilders(){ return builders; } /** * A layer may provide a graphic builder, this enable * special representations, like wind arrows for coverages. * A layer may have different builder for each kind of Graphic implementation. * This enable the possibility to have custom made graphic representation * and several builder, for 2D,3D or else... * * @param type : the graphic type wanted * @return graphicBuilder<? extends type> or null */ @Override public <T extends Graphic> GraphicBuilder<? extends T> getGraphicBuilder( final Class<T> type ){ for(GraphicBuilder builder : builders){ if(type.isAssignableFrom(builder.getGraphicType())){ return builder; } } return null; } //-------------------------------------------------------------------------- // listeners management ---------------------------------------------------- //-------------------------------------------------------------------------- protected void fireStyleChange(final EventObject event){ //TODO make fire property change thread safe, preserve fire order final LayerListener[] lists = listeners.getListeners(LayerListener.class); for(LayerListener listener : lists){ listener.styleChange(this, event); } //fire a property change for others firePropertyChange(STYLE_PROPERTY, this.getStyle(), this.getStyle()); } //-------------------------------------------------------------------------- // style listener----------------------------------------------------------- //-------------------------------------------------------------------------- @Override public void propertyChange(final PropertyChangeEvent event) { fireStyleChange(event); } @Override public void featureTypeStyleChange(final CollectionChangeEvent<MutableFeatureTypeStyle> event) { fireStyleChange(event); } /** * {@inheritDoc } */ @Override public void addLayerListener(final LayerListener listener){ synchronized(listeners){ listeners.add(LayerListener.class, listener); addItemListener(listener); } } /** * {@inheritDoc } */ @Override public void removeLayerListener(final LayerListener listener){ synchronized(listeners){ listeners.remove(LayerListener.class, listener); removeItemListener(listener); } } }