/*
* This is part of Geomajas, a GIS framework, http://www.geomajas.org/.
*
* Copyright 2008-2015 Geosparc nv, http://www.geosparc.com/, Belgium.
*
* The program is available in open source according to the GNU Affero
* General Public License. All contributions in this program are covered
* by the Geomajas Contributors License Agreement. For full licensing
* details, see LICENSE.txt in the project root.
*/
package org.geomajas.gwt2.client.widget.legend;
import com.google.gwt.http.client.URL;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import org.geomajas.annotation.Api;
import org.geomajas.configuration.NamedStyleInfo;
import org.geomajas.gwt2.client.GeomajasServerExtension;
import org.geomajas.gwt2.client.event.LayerStyleChangedEvent;
import org.geomajas.gwt2.client.event.LayerStyleChangedHandler;
import org.geomajas.gwt2.client.event.ViewPortChangedEvent;
import org.geomajas.gwt2.client.event.ViewPortChangedHandler;
import org.geomajas.gwt2.client.map.MapEventBus;
import org.geomajas.gwt2.client.map.ViewPort;
import org.geomajas.gwt2.client.map.layer.VectorServerLayer;
import org.geomajas.sld.FeatureTypeStyleInfo;
import org.geomajas.sld.RuleInfo;
import java.util.ArrayList;
import java.util.List;
/**
* Widget that represents the legend for a {@link VectorServerLayer}. This legend will only display the currently
* visible styles and update automatically. For example, every style rule may have a minimum and/or maximum scale range.
* Should the map be out of that range, the corresponding style will be made invisible.<br/>
* This legend will also react to {@link LayerStyleChangedEvent}s to update automatically.
*
*
* @author Pieter De Graef
* @since 2.0.0
*/
@Api(allMethods = true)
public class DynamicVectorServerLayerLegend implements IsWidget {
private final List<ServerLayerStyleWidget> ruleWidgets = new ArrayList<ServerLayerStyleWidget>();
private final ViewPort viewPort;
private final VectorServerLayer layer;
private VerticalPanel layout;
/**
* Create a new legend widget.
*
* @param eventBus
* The map eventbus. Used to react to the correct events to update the legend content.
* @param viewPort
* The viewport.
* @param layer
* The layer for which to build a legend.
*/
protected DynamicVectorServerLayerLegend(MapEventBus eventBus, ViewPort viewPort, VectorServerLayer layer) {
this.viewPort = viewPort;
this.layer = layer;
// Zooming in or out may cause some styles to become visible/invisible:
eventBus.addViewPortChangedHandler(new ViewPortChangedHandler() {
public void onViewPortChanged(ViewPortChangedEvent event) {
updateVisibility();
}
});
// Update the legend widget when the style on this layer changes:
eventBus.addLayerStyleChangedHandler(new LayerStyleChangedHandler() {
@Override
public void onLayerStyleChanged(LayerStyleChangedEvent event) {
layout.clear();
buildLegend(layout);
}
}, layer);
}
@Override
public Widget asWidget() {
if (layout == null) {
layout = new VerticalPanel();
buildLegend(layout);
}
return layout;
}
/**
* Get the layer for this legend.
*
* @return The layer.s
*/
public VectorServerLayer getLayer() {
return layer;
}
// ------------------------------------------------------------------------
// Private methods:
// ------------------------------------------------------------------------
private void buildLegend(VerticalPanel layout) {
NamedStyleInfo styleInfo = layer.getLayerInfo().getNamedStyleInfo();
int i = 0;
for (FeatureTypeStyleInfo sfi : styleInfo.getUserStyle().getFeatureTypeStyleList()) {
for (RuleInfo rInfo : sfi.getRuleList()) {
String url = GeomajasServerExtension.getInstance().getEndPointService().getLegendServiceUrl();
ServerLayerStyleWidget.addPath(url, layer.getServerLayerId());
ServerLayerStyleWidget.addPath(url, styleInfo.getName());
ServerLayerStyleWidget.addPath(url, i + ".png");
ServerLayerStyleWidget widget = new ServerLayerStyleWidget(URL.encode(url), rInfo.getName(), rInfo);
ruleWidgets.add(widget);
layout.add(widget);
i++;
}
}
}
private void updateVisibility() {
for (ServerLayerStyleWidget ruleWidget : ruleWidgets) {
ruleWidget.asWidget().setVisible(isVisible(ruleWidget.getRule(), viewPort));
}
}
/** TODO This method might be interesting as a static method in some SLD utility class. */
private boolean isVisible(RuleInfo rule, ViewPort viewPort) {
if (rule == null) {
return true;
}
double minResolution = Double.MAX_VALUE;
double maxResolution = Double.MIN_VALUE;
if (rule.getMinScaleDenominator() != null && rule.getMinScaleDenominator().getMinScaleDenominator() != 0) {
maxResolution = viewPort.toResolution(rule.getMinScaleDenominator().getMinScaleDenominator());
}
if (rule.getMaxScaleDenominator() != null && rule.getMaxScaleDenominator().getMaxScaleDenominator() != 0) {
minResolution = viewPort.toResolution(rule.getMaxScaleDenominator().getMaxScaleDenominator());
}
return (maxResolution <= viewPort.getResolution() && viewPort.getResolution() < minResolution);
}
}