Package org.geomajas.gwt.client.map.cache.tile

Source Code of org.geomajas.gwt.client.map.cache.tile.VectorTile

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

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.geomajas.command.CommandResponse;
import org.geomajas.command.dto.GetVectorTileRequest;
import org.geomajas.command.dto.GetVectorTileResponse;
import org.geomajas.gwt.client.command.CommandCallback;
import org.geomajas.gwt.client.command.Deferred;
import org.geomajas.gwt.client.command.GwtCommand;
import org.geomajas.gwt.client.command.GwtCommandDispatcher;
import org.geomajas.gwt.client.gfx.PaintableGroup;
import org.geomajas.gwt.client.gfx.PainterVisitor;
import org.geomajas.gwt.client.map.cache.SpatialCache;
import org.geomajas.gwt.client.map.feature.Feature;
import org.geomajas.gwt.client.map.feature.LazyLoadCallback;
import org.geomajas.gwt.client.map.feature.LazyLoader;
import org.geomajas.gwt.client.spatial.Bbox;
import org.geomajas.layer.tile.TileCode;
import org.geomajas.layer.tile.VectorTile.VectorTileContentType;

import com.google.gwt.core.client.GWT;
import com.smartgwt.client.util.SC;

/**
* Representation of a vector tile in the GWT client.
*
* @author Pieter De Graef
*/
public class VectorTile extends AbstractVectorTile {

  /**
   * Data holder: contains SVG or VML from the server for features.
   */
  private ContentHolder featureContent;

  /**
   * Data holder: contains SVG or VML from the server for labels.
   */
  private ContentHolder labelContent;

  private VectorTileContentType contentType;

  /** width in screen units */
  private double screenWidth;

  /** height in screen units */
  private double screenHeight;

  /** dependent tile codes */
  private List<TileCode> codes = new ArrayList<TileCode>();

  private Set<GetVectorTileRequest> requestCache = new HashSet<GetVectorTileRequest>();

  private Deferred deferred;

  // -------------------------------------------------------------------------
  // Constructors:
  // -------------------------------------------------------------------------

  public VectorTile(TileCode code, Bbox bbox, SpatialCache cache) {
    super(code, bbox, cache);
    featureContent = new ContentHolder(code.toString());
    labelContent = new ContentHolder(code.toString());
  }

  // -------------------------------------------------------------------------
  // Spatial node functions:
  // -------------------------------------------------------------------------

  /**
   * Return all features in this tile. Warning : this will not return the features from other tiles that intersect
   * with this tile ! If you want to interact with all features, use the query() method.
   *
   * @param featureIncludes
   *            what data should be available in the features
   * @param callback
   *            callback which gets the features
   * @deprecated features are no longer included in the tile
   */
  @Deprecated
  public void getFeatures(int featureIncludes, LazyLoadCallback callback) {
    List<Feature> list = new ArrayList<Feature>();
    LazyLoader.lazyLoad(list, featureIncludes, callback);
  }

  /**
   * Return all partial features in this tile. Warning : this will return possibly incomplete features !
   *
   * @return a list of all features in this tile
   * @deprecated features are no longer included in the tile
   */
  @Deprecated
  public List<Feature> getPartialFeatures() {
    return new ArrayList<Feature>();
  }

  /**
   * Fetch all data related to this tile.
   *
   * @param filter
   *            When fetching it is possible to filter the data with this filter object. Null otherwise.
   * @param callback
   *            When this node's data comes from the server, it will be handled by this callback function.
   */
  public void fetch(final String filter, final TileFunction<VectorTile> callback) {
    final GetVectorTileRequest request = createRequest(filter);
    GwtCommand command = new GwtCommand(GetVectorTileRequest.COMMAND);
    command.setCommandRequest(request);
    final VectorTile self = this;
    deferred = GwtCommandDispatcher.getInstance().execute(command, new CommandCallback<GetVectorTileResponse>() {

      public void execute(GetVectorTileResponse response) {
        if (!(deferred != null && deferred.isCancelled())) {
          GetVectorTileResponse tileResponse = (GetVectorTileResponse) response;
          org.geomajas.layer.tile.VectorTile tile = tileResponse.getTile();
          for (TileCode relatedTile : tile.getCodes()) {
            codes.add(relatedTile);
          }
          code = tile.getCode();
          screenWidth = tile.getScreenWidth();
          screenHeight = tile.getScreenHeight();
          contentType = tile.getContentType();
          switch (contentType) {
            case STRING_CONTENT:
              featureContent.setContent(tile.getFeatureContent());
              labelContent.setContent(tile.getLabelContent());
              break;
            case URL_CONTENT:
              if (request.isPaintLabels()) {
                if (tile.getLabelContent() == null) {
                  // feature content may also contain labels !
                  labelContent.setContent(tile.getFeatureContent());
                } else {
                  labelContent.setContent(tile.getLabelContent());
                }
              } else {
                featureContent.setContent(tile.getFeatureContent());
              }
              break;

          }
          requestCache.add(request);
          try {
            callback.execute(self);
          } catch (Throwable t) {
            GWT.log("VectorTile: error calling the callback after a fetch.", t);
          }
        }
        deferred = null;
      }
    });
  }

  /**
   * Execute a <code>TileFunction</code> in this tile and all connected tiles. If these connected tiles are not yet
   * part of the cache, then they will be fetched before applying the <code>TileFunction</code> on them.
   *
   * @param filter
   *            A possible filter that needs to be used in case connected tile need to be fetched.
   * @param callback
   *            The actual <code>TileFunction</code> to be executed on the connected tiles.
   */
  public void applyConnected(final String filter, final TileFunction<VectorTile> callback) {
    apply(filter, new TileFunction<VectorTile>() {

      public void execute(VectorTile tile) {
        List<TileCode> tileCodes = tile.getCodes();
        for (TileCode tileCode : tileCodes) {
          VectorTile temp = tile.cache.addTile(tileCode);
          if (temp.getStatus() == STATUS.EMPTY) {
            temp.fetch(filter, callback);
          } else {
            temp.apply(filter, callback);
          }
        }
      }
    });
  }

  /**
   * Execute a TileFunction on this tile. If the tile is not yet loaded, attach it to the isLoaded event.
   *
   * @param filter
   *            filter which needs to be applied when fetching
   * @param callback
   *            callback to call
   */
  public void apply(final String filter, final TileFunction<VectorTile> callback) {
    switch (getStatus()) {
      case EMPTY:
        fetch(filter, callback);
        break;
      case LOADING:
        final VectorTile self = this;
        deferred.addCallback(new CommandCallback() {

          public void execute(CommandResponse response) {
            if (response instanceof GetVectorTileResponse) {
              callback.execute(self);
            }
          }
        });
        break;
      case LOADED:
        if (needsReload(filter)) {
          // Check if the labels need to be fetched as well:
          fetch(filter, callback);
        } else {
          callback.execute(this);
        }
    }
  }

  /**
   * Return the current status of this VectorTile. Can be one of the following:
   * <ul>
   * <li>STATUS.EMPTY</li>
   * <li>STATUS.LOADING</li>
   * <li>STATUS.LOADED</li>
   * </ul>
   */
  public STATUS getStatus() {
    if (featureContent.isLoaded()) {
      return STATUS.LOADED;
    }
    if (deferred == null) {
      return STATUS.EMPTY;
    }
    return STATUS.LOADING;
  }

  /**
   * Cancel the fetching of this tile. No callback will be executed anymore.
   */
  public void cancel() {
    if (deferred != null) {
      deferred.cancel();
    }
  }

  // -------------------------------------------------------------------------
  // Some getters and setters:
  // -------------------------------------------------------------------------

  public List<TileCode> getCodes() {
    return codes;
  }

  public double getScreenWidth() {
    return screenWidth;
  }

  public double getScreenHeight() {
    return screenHeight;
  }

  public ContentHolder getFeatureContent() {
    return featureContent;
  }

  public ContentHolder getLabelContent() {
    return labelContent;
  }

  public VectorTileContentType getContentType() {
    return contentType;
  }

  /**
   * Holds string content.
   *
   * @author Jan De Moerloose
   */
  public class ContentHolder implements PaintableGroup {

    private String groupName;

    private String content;

    ContentHolder(String groupName) {
      this.groupName = groupName;
    }

    public String getGroupName() {
      return groupName;
    }

    public String getContent() {
      return content;
    }

    public void setContent(String content) {
      this.content = content;
    }

    public boolean isLoaded() {
      return content != null;
    }

    public void accept(PainterVisitor visitor, Object group, Bbox bounds, boolean recursive) {
    }
  }
 
  private boolean needsReload(String filter) {
    GetVectorTileRequest request = createRequest(filter);
    return !requestCache.contains(request);
  }

  // -------------------------------------------------------------------------
  // Private methods:
  // -------------------------------------------------------------------------

  private GetVectorTileRequest createRequest(String filter) {
    GetVectorTileRequest request = new GetVectorTileRequest();
    request.setCode(code);
    request.setCrs(cache.getLayer().getMapModel().getCrs());
    request.setFilter(filter);
    request.setLayerId(cache.getLayer().getServerLayerId());
    // always paint geometries, except when we already have the svg/vml
    request.setPaintGeometries(!(VectorTileContentType.STRING_CONTENT == contentType && featureContent.isLoaded()));
    request.setPaintLabels(cache.getLayer().isLabeled());
    request.setPanOrigin(cache.getLayer().getMapModel().getMapView().getPanOrigin());
    request.setRenderer(SC.isIE() ? "VML" : "SVG");
    request.setScale(cache.getLayer().getMapModel().getMapView().getCurrentScale());
    request.setStyleInfo(cache.getLayer().getLayerInfo().getNamedStyleInfo());
    return request;
  }

}
TOP

Related Classes of org.geomajas.gwt.client.map.cache.tile.VectorTile

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.