/*
Copyright (C) 2001, 2006 United States Government
as represented by the Administrator of the
National Aeronautics and Space Administration.
All Rights Reserved.
*/
package gov.nasa.worldwind.layers;
import gov.nasa.worldwind.WWObjectImpl;
import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.geom.Position;
import gov.nasa.worldwind.render.DrawContext;
import gov.nasa.worldwind.util.Logging;
/**
* @author tag
* @version $Id: AbstractLayer.java 4442 2008-02-12 09:57:40Z tgaskins $
*/
public abstract class AbstractLayer extends WWObjectImpl implements Layer
{
private boolean enabled = true;
private boolean pickable = true;
private double opacity = 1d;
private double minActiveAltitude = -Double.MAX_VALUE;
private double maxActiveAltitude = Double.MAX_VALUE;
public boolean isEnabled()
{
return this.enabled;
}
public boolean isPickEnabled()
{
return pickable;
}
public void setPickEnabled(boolean pickable)
{
this.pickable = pickable;
}
public void setEnabled(boolean enabled)
{
this.enabled = enabled;
}
public String getName()
{
Object n = this.getValue(AVKey.DISPLAY_NAME);
return n != null ? n.toString() : this.toString();
}
public void setName(String name)
{
this.setValue(AVKey.DISPLAY_NAME, name);
}
public String toString()
{
Object n = this.getValue(AVKey.DISPLAY_NAME);
return n != null ? n.toString() : super.toString();
}
public double getOpacity()
{
return opacity;
}
public void setOpacity(double opacity)
{
this.opacity = opacity;
}
public double getMinActiveAltitude()
{
return minActiveAltitude;
}
public void setMinActiveAltitude(double minActiveAltitude)
{
this.minActiveAltitude = minActiveAltitude;
}
public double getMaxActiveAltitude()
{
return maxActiveAltitude;
}
public void setMaxActiveAltitude(double maxActiveAltitude)
{
this.maxActiveAltitude = maxActiveAltitude;
}
public double getScale()
{
Object o = this.getValue(AVKey.MAP_SCALE);
return o != null && o instanceof Double ? (Double) o : 1;
}
/**
* Indicates whether the layer is in the view. The method implemented here is a default indicating the layer is in
* view. Subclasses able to determine their presence in the view should override this implementation.
*
* @param dc the current draw context
* @return <code>true</code> if the layer is in the view, <code>false</code> otherwise.
*/
public boolean isLayerInView(DrawContext dc)
{
if (dc == null)
{
String message = Logging.getMessage("nullValue.DrawContextIsNull");
Logging.logger().severe(message);
throw new IllegalStateException(message);
}
return true;
}
/**
* Indicates whether the layer is active based on arbitrary criteria. The method implemented here is a default
* indicating the layer is active if the current altitude is within the layer's min and max active altitudes.
* Subclasses able to consider more criteria should override this implementation.
*
* @param dc the current draw context
* @return <code>true</code> if the layer is active, <code>false</code> otherwise.
*/
public boolean isLayerActive(DrawContext dc)
{
if (dc == null)
{
String message = Logging.getMessage("nullValue.DrawContextIsNull");
Logging.logger().severe(message);
throw new IllegalStateException(message);
}
if (null == dc.getView())
{
String message = Logging.getMessage("layers.AbstractLayer.NoViewSpecifiedInDrawingContext");
Logging.logger().severe(message);
throw new IllegalStateException(message);
}
Position eyePos = dc.getView().getEyePosition();
if (eyePos == null)
return false;
double altitude = eyePos.getElevation();
return altitude >= this.minActiveAltitude && altitude <= this.maxActiveAltitude;
}
/**
* @param dc the current draw context
* @throws IllegalArgumentException if <code>dc</code> is null, or <code>dc</code>'s <code>Globe</code> or
* <code>View</code> is null
*/
public void render(DrawContext dc)
{
if (!this.enabled)
return; // Don't check for arg errors if we're disabled
if (null == dc)
{
String message = Logging.getMessage("nullValue.DrawContextIsNull");
Logging.logger().severe(message);
throw new IllegalStateException(message);
}
if (null == dc.getGlobe())
{
String message = Logging.getMessage("layers.AbstractLayer.NoGlobeSpecifiedInDrawingContext");
Logging.logger().severe(message);
throw new IllegalStateException(message);
}
if (null == dc.getView())
{
String message = Logging.getMessage("layers.AbstractLayer.NoViewSpecifiedInDrawingContext");
Logging.logger().severe(message);
throw new IllegalStateException(message);
}
if (!this.isLayerActive(dc))
return;
if (!this.isLayerInView(dc))
return;
this.doRender(dc);
}
public void pick(DrawContext dc, java.awt.Point point)
{
if (!this.enabled)
return; // Don't check for arg errors if we're disabled
if (null == dc)
{
String message = Logging.getMessage("nullValue.DrawContextIsNull");
Logging.logger().severe(message);
throw new IllegalStateException(message);
}
if (null == dc.getGlobe())
{
String message = Logging.getMessage("layers.AbstractLayer.NoGlobeSpecifiedInDrawingContext");
Logging.logger().severe(message);
throw new IllegalStateException(message);
}
if (null == dc.getView())
{
String message = Logging.getMessage("layers.AbstractLayer.NoViewSpecifiedInDrawingContext");
Logging.logger().severe(message);
throw new IllegalStateException(message);
}
if (!this.isLayerActive(dc))
return;
if (!this.isLayerInView(dc))
return;
this.doPick(dc, point);
}
protected void doPick(DrawContext dc, java.awt.Point point)
{
// any state that could change the color needs to be disabled, such as GL_TEXTURE, GL_LIGHTING or GL_FOG.
// re-draw with unique colors
// store the object info in the selectable objects table
// read the color under the coursor
// use the color code as a key to retrieve a selected object from the selectable objects table
// create an instance of the PickedObject and add to the dc via the dc.addPickedObject() method
}
public void dispose() // override if disposal is a supported operation
{
}
protected abstract void doRender(DrawContext dc);
public boolean isAtMaxResolution()
{
return this.isMultiResolution() ? false : true;
}
public boolean isMultiResolution()
{
return false;
}
public String getRestorableState()
{
return null;
}
public void restoreState(String stateInXml)
{
String message = Logging.getMessage("RestorableSupport.RestoreNotSupported");
Logging.logger().severe(message);
throw new UnsupportedOperationException(message);
}
}