All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.geomajas.gwt2.client.map.render.RasterLayerScaleRenderer Maven / Gradle / Ivy

/*
 * This is part of Geomajas, a GIS framework, http://www.geomajas.org/.
 *
 * Copyright 2008-2013 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.map.render;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.geomajas.command.dto.GetRasterTilesRequest;
import org.geomajas.command.dto.GetRasterTilesResponse;
import org.geomajas.geometry.Bbox;
import org.geomajas.geometry.service.BboxService;
import org.geomajas.gwt.client.command.AbstractCommandCallback;
import org.geomajas.gwt.client.command.Deferred;
import org.geomajas.gwt.client.command.GwtCommand;
import org.geomajas.layer.tile.RasterTile;
import org.geomajas.layer.tile.TileCode;
import org.geomajas.gwt2.client.event.ScaleLevelRenderedEvent;
import org.geomajas.gwt2.client.gfx.HtmlContainer;
import org.geomajas.gwt2.client.gfx.HtmlImage;
import org.geomajas.gwt2.client.gfx.HtmlImageFactory;
import org.geomajas.gwt2.client.map.layer.RasterServerLayer;
import org.geomajas.gwt2.client.service.CommandService;

import com.google.gwt.core.client.Callback;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.google.web.bindery.event.shared.EventBus;

/**
 * 

* Presenter for a certain fixed scale level of a {@link RasterServerLayer}. It retrieves, stores and displays raster * tiles for a single raster layer at a single scale level. *

*

* Rendering new or extra tiles is a 2-step process: first the correct list of tiles is fetched, then their images are * retrieved. Both steps end in a call to an abstract method. For fetching tiles, this is "onTilesReceived" *

* * @author Pieter De Graef */ public class RasterLayerScaleRenderer implements LayerScaleRenderer { private CommandService commandService; private HtmlImageFactory htmlImageFactory; private EventBus eventBus; private final String crs; private final RasterServerLayer rasterLayer; private final HtmlContainer container; private final double scale; private final Map tiles; // Settings and status variables: private double mapExtentScaleAtFetch = 1; private Deferred deferred; private Bbox currentTileBounds; private int nrLoadingTiles; private boolean renderingImages; private Object eventSource; // ------------------------------------------------------------------------ // Constructors: // ------------------------------------------------------------------------ @Inject public RasterLayerScaleRenderer(EventBus eventBus, CommandService commandService, HtmlImageFactory htmlImageFactory, @Assisted Object eventSource, @Assisted String crs, @Assisted RasterServerLayer rasterLayer, @Assisted HtmlContainer container, @Assisted double scale) { this.eventBus = eventBus; this.commandService = commandService; this.htmlImageFactory = htmlImageFactory; this.eventSource = eventSource; this.crs = crs; this.rasterLayer = rasterLayer; this.container = container; this.scale = scale; tiles = new HashMap(); } // ------------------------------------------------------------------------ // Public methods: // ------------------------------------------------------------------------ @Override public void onScaleRendered(HtmlContainer container, double scale) { eventBus.fireEventFromSource(new ScaleLevelRenderedEvent(scale), eventSource); } @Override public void cancel() { if (deferred != null) { deferred.cancel(); deferred = null; currentTileBounds = null; } } @Override public double getScale() { return scale; } @Override public void render(final Bbox bounds) { if (rasterLayer.isShowing()) { // First we check whether or not the requested bounds is already rendered: if (currentTileBounds != null && BboxService.contains(currentTileBounds, bounds)) { onScaleRendered(container, scale); return; // Bounds already rendered, nothing to do here. } // Scale the bounds to fetch tiles for (we want a bigger area than the map bounds): currentTileBounds = BboxService.scale(bounds, mapExtentScaleAtFetch); // Create the command: GetRasterTilesRequest request = new GetRasterTilesRequest(); request.setBbox(new org.geomajas.geometry.Bbox(currentTileBounds.getX(), currentTileBounds.getY(), currentTileBounds.getWidth(), currentTileBounds.getHeight())); request.setCrs(crs); request.setLayerId(rasterLayer.getServerLayerId()); request.setScale(scale); GwtCommand command = new GwtCommand(GetRasterTilesRequest.COMMAND); command.setCommandRequest(request); // Execute the fetch, and render on success: deferred = commandService.execute(command, new AbstractCommandCallback() { public void execute(GetRasterTilesResponse response) { addTiles(response.getRasterData()); } }); } } public boolean isRendered() { return nrLoadingTiles > 0; } // ------------------------------------------------------------------------ // Getters and setters: // ------------------------------------------------------------------------ public boolean isFetchingTiles() { return deferred != null; } public boolean isRenderingImages() { return renderingImages; } public HtmlContainer getHtmlContainer() { return container; } public double getMapExtentScaleAtFetch() { return mapExtentScaleAtFetch; } public void setMapExtentScaleAtFetch(double mapExtentScaleAtFetch) { this.mapExtentScaleAtFetch = mapExtentScaleAtFetch; } // ------------------------------------------------------------------------ // Private methods and classes: // ------------------------------------------------------------------------ protected void addTiles(List rasterTiles) { nrLoadingTiles = 0; for (RasterTile tile : rasterTiles) { TileCode code = tile.getCode().clone(); // Add only new tiles to the list: if (!tiles.containsKey(code)) { nrLoadingTiles++; // Add the tile to the list and render it: tiles.put(code, tile); renderTile(tile, new ImageCounter()); } } deferred = null; renderingImages = true; } protected void renderTile(RasterTile tile, Callback callback) { HtmlImage image = htmlImageFactory.create(tile.getUrl(), tile.getBounds(), callback); container.add(image); } /** * Counts the number of images that are still inbound. If all images are effectively rendered, we call * {@link #onTilesRendered}. * * @author Pieter De Graef */ private class ImageCounter implements Callback { // In case of failure, we can't just sit and wait. Instead we immediately consider the scale level rendered. public void onFailure(String reason) { onScaleRendered(container, scale); } public void onSuccess(String result) { nrLoadingTiles--; if (nrLoadingTiles == 0) { onScaleRendered(container, scale); } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy