/*
* Copyright (C) 2015 by Array Systems Computing Inc. http://www.array.ca
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version.
* This program 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 General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see http://www.gnu.org/licenses/
*/
package org.esa.snap.worldwind;
import gov.nasa.worldwind.WorldWindow;
import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.event.SelectEvent;
import gov.nasa.worldwind.layers.Layer;
import gov.nasa.worldwind.layers.LayerList;
import gov.nasa.worldwind.pick.PickedObject;
import gov.nasa.worldwind.render.ScreenAnnotation;
import gov.nasa.worldwindx.examples.util.LayerManagerLayer;
import java.awt.*;
/**
* Displays the layer list in a viewport corner.
*/
public class LayerPanelLayer extends LayerManagerLayer {
private Layer virtualEarthAerialLayer = null;
private Layer virtualEarthRoadsLayer = null;
private Layer virtualEarthHybridLayer = null;
public LayerPanelLayer(WorldWindow wwd) {
super(wwd);
}
private LayerList getValidLayers() {
final LayerList validLayers = new LayerList();
final LayerList allLayers = wwd.getModel().getLayers();
for (Layer l : allLayers) {
if (l.getName().equalsIgnoreCase("Atmosphere") || l.getName().equalsIgnoreCase("World Map") ||
l.getName().equalsIgnoreCase("Scale bar") || l.getName().equalsIgnoreCase("Compass") ||
l.getName().equalsIgnoreCase("NASA Blue Marble Image"))
continue;
if (l.getName().equalsIgnoreCase("MS Bing Aerial"))
virtualEarthAerialLayer = l;
else if (l.getName().equalsIgnoreCase("MS Bing Roads"))
virtualEarthRoadsLayer = l;
else if (l.getName().equalsIgnoreCase("MS Bing Hybrid"))
virtualEarthHybridLayer = l;
validLayers.add(l);
}
return validLayers;
}
/**
* <code>SelectListener</code> implementation.
*
* @param event the current <code>SelectEvent</code>
*/
@Override
public void selected(SelectEvent event) {
//System.out.println("event.getEventAction(): " + event.getEventAction());
final ScreenAnnotation annotation = getAnnotation();
if (event.hasObjects() && event.getTopObject() == annotation) {
boolean update = false;
if (event.getEventAction().equals(SelectEvent.ROLLOVER)
|| event.getEventAction().equals(SelectEvent.LEFT_CLICK)) {
// Highlight annotation
if (!annotation.getAttributes().isHighlighted()) {
annotation.getAttributes().setHighlighted(true);
update = true;
}
// Check for text or url
final PickedObject po = event.getTopPickedObject();
if (po.getValue(AVKey.URL) != null) {
// Set cursor hand on hyperlinks
((Component) this.wwd).setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
int i = Integer.parseInt((String) po.getValue(AVKey.URL));
// Select current hyperlink
if (getSelectedIndex() != i) {
setSelectedIndex(i);
update = true;
}
// Enable/disable layer on left click
if (event.getEventAction().equals(SelectEvent.LEFT_CLICK)) {
final LayerList layers = getValidLayers();
if (i >= 0 && i < layers.size()) {
final Layer layer = layers.get(i);
final boolean enable = !layer.isEnabled();
layer.setEnabled(enable);
updateVirtualEarthLayers(layer, enable);
update = true;
}
}
} else {
// Unselect if not on an hyperlink
if (getSelectedIndex() != -1) {
setSelectedIndex(-1);
update = true;
}
// Set cursor
if (this.isComponentDragEnabled())
((Component) this.wwd).setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
else
((Component) this.wwd).setCursor(Cursor.getDefaultCursor());
}
}
if (event.getEventAction().equals(SelectEvent.DRAG)
|| event.getEventAction().equals(SelectEvent.DRAG_END)) {
// Handle dragging
if (this.isComponentDragEnabled() || this.isLayerDragEnabled()) {
final boolean wasDraggingLayer = this.draggingLayer;
this.drag(event);
// Update list if dragging a layer, otherwise just redraw the world window
if (this.draggingLayer || wasDraggingLayer)
update = true;
else
this.wwd.redraw();
}
}
// Redraw annotation if needed
if (update)
this.update();
} else if (event.getEventAction().equals(SelectEvent.ROLLOVER) && annotation.getAttributes().isHighlighted()) {
// de-highlight annotation
annotation.getAttributes().setHighlighted(false);
((Component) this.wwd).setCursor(Cursor.getDefaultCursor());
this.update();
}
}
private void updateVirtualEarthLayers(Layer layer, boolean enable) {
if (enable && (layer == virtualEarthAerialLayer ||
layer == virtualEarthRoadsLayer ||
layer == virtualEarthHybridLayer)) {
virtualEarthAerialLayer.setEnabled(layer == virtualEarthAerialLayer);
virtualEarthRoadsLayer.setEnabled(layer == virtualEarthRoadsLayer);
virtualEarthHybridLayer.setEnabled(layer == virtualEarthHybridLayer);
}
}
@Override
protected void drag(SelectEvent event) {
if (event.getEventAction().equals(SelectEvent.DRAG)) {
if ((this.isComponentDragEnabled() && getSelectedIndex() == -1 && this.dragRefIndex == -1)
|| this.draggingComponent) {
// Dragging the whole list
if (!this.draggingComponent) {
this.dragRefCursorPoint = event.getMouseEvent().getPoint();
this.dragRefPoint = getAnnotation().getScreenPoint();
this.draggingComponent = true;
}
final Point cursorOffset = new Point(event.getMouseEvent().getPoint().x - this.dragRefCursorPoint.x,
event.getMouseEvent().getPoint().y - this.dragRefCursorPoint.y);
final Point targetPoint = new Point(this.dragRefPoint.x + cursorOffset.x,
this.dragRefPoint.y - cursorOffset.y);
this.moveTo(targetPoint);
} else if (this.isLayerDragEnabled()) {
// Dragging a layer inside the list
if (!this.draggingLayer) {
this.dragRefIndex = getSelectedIndex();
this.draggingLayer = true;
}
if (getSelectedIndex() != -1 && this.dragRefIndex != -1 && this.dragRefIndex != getSelectedIndex()) {
// Move dragged layer
final LayerList layers = getValidLayers();
final int insertIndex = this.dragRefIndex > getSelectedIndex() ?
getSelectedIndex() : getSelectedIndex() + 1;
final int removeIndex = this.dragRefIndex > getSelectedIndex() ?
this.dragRefIndex + 1 : this.dragRefIndex;
layers.add(insertIndex, layers.get(this.dragRefIndex));
layers.remove(removeIndex);
this.dragRefIndex = getSelectedIndex();
}
}
} else if (event.getEventAction().equals(SelectEvent.DRAG_END)) {
this.draggingComponent = false;
this.draggingLayer = false;
this.dragRefIndex = -1;
}
}
/**
* Compose the annotation text from the given <code>LayerList</code>.
*
* @param layers the <code>LayerList</code> to draw names from.
* @return the annotation text to be displayed.
*/
@Override
protected String makeAnnotationText(LayerList layers) {
// Compose html text
final StringBuilder text = new StringBuilder(255);
Color color;
int i = 0;
final LayerList validLayers = getValidLayers();
for (Layer layer : validLayers) {
if (!this.isMinimized() || layer == this) {
color = (i == getSelectedIndex()) ? getHighlightColor() : getColor();
color = (i == this.dragRefIndex) ? dragColor : color;
text.append("<a href=\"");
text.append(i);
text.append("\"><font color=\"");
text.append(encodeHTMLColor(color));
text.append("\">");
text.append((layer.isEnabled() ? getLayerEnabledSymbol() : getLayerDisabledSymbol()));
text.append(' ');
text.append((layer.isEnabled() ? "<b>" : "<i>"));
text.append(layer.getName());
text.append((layer.isEnabled() ? "</b>" : "</i>"));
text.append((layer.isMultiResolution() && layer.isAtMaxResolution() ? "*" : ""));
text.append("</a><br />");
}
i++;
}
return text.toString();
}
}