Source: style/stylecluster.js

goog.provide('M.style.Cluster');
goog.require('M.Style');
/**
 * @namespace M.style.Cluster
 */
(function() {
  /**
   * @classdesc
   * Main constructor of the class. Creates a style cluster
   * with parameters specified by the user
   *
   * @constructor
   * @extends {M.Style}
   * @param {object} parameters for style cluster
   * @param {object} specified parameters for class claster depends on its implementation
   * @api stable
   */
  M.style.Cluster = (function(options = {}, optsVendor = {}) {
    M.utils.extends(options, M.style.Cluster.DEFAULT);
    M.utils.extends(optsVendor, M.style.Cluster.DEFAULT_VENDOR);

    /**
     * @private
     * @type {Object}
     */
    this.oldStyle_ = null;

    var impl = new M.impl.style.Cluster(options, optsVendor);

    // calls the super constructor
    goog.base(this, options, impl);
  });
  goog.inherits(M.style.Cluster, M.Style);

  /**
   * This function unapply the style to specified layer
   * @function
   * @public
   * @param {M.layer.Vector} layer layer to unapply his style
   * @api stable
   */
  M.style.Cluster.prototype.unapply = function(layer) {
    this.getImpl().unapply();
  };

  /**
   * This function apply style to specified layer
   *
   * @function
   * @public
   * @param {M.layer.Vector} layer - Layer to apply the style
   * @api stable
   */
  M.style.Cluster.prototype.apply = function(layer) {
    let newStyle = layer.getStyle();
    if (!(newStyle instanceof M.style.Cluster)) {
      this.oldStyle_ = newStyle;
    }
    else {
      this.oldStyle_ = newStyle.getOldStyle();
    }
    goog.base(this, 'apply', layer);
  };

  /**
   * This function gets the old style of layer
   * @function
   * @public
   * @return {M.Style} the old style of layer
   * @api stable
   */
  M.style.Cluster.prototype.getOldStyle = function() {
    return this.oldStyle_;
  };

  /**
   * This function return a set of ranges defined by user
   *
   * @function
   * @public
   * @return {Array<Object>} ranges stablished by user
   * @api stable
   */
  M.style.Cluster.prototype.getRanges = function() {
    return this.options_.ranges;
  };

  /**
   * This function returns the options of style cluster
   * @function
   * @public
   * @return {object} options of style cluster
   * @api stable
   */
  M.style.Cluster.prototype.getOptions = function() {
    return this.options_;
  };

  /**
   * This function update a set of ranges  defined by user
   *
   * @function
   * @public
   * @param {Array<Object>} newRanges as new Ranges
   * @return {M.style.Cluster}
   * @api stable
   */
  M.style.Cluster.prototype.setRanges = function(newRanges) {
    this.getImpl().setRanges(newRanges);
    this.unapply(this.layer_);
    this.layer_.setStyle(this);
    return this;
  };

  /**
   * This function return a specified range
   *
   * @function
   * @public
   * @param {number} min as minimal value in the interval
   * @param {number} max as max value in the interval
   * @return {Object}
   * @api stable
   */
  M.style.Cluster.prototype.getRange = function(min, max) {
    return this.options_.ranges.find(el => (el.min == min && el.max == max));
  };

  /**
   * This function set a specified range
   *
   * @function
   * @public
   * @param {number} min as range minimal value to be overwritten
   * @param {number} max as range max value to be overwritten
   * @param {number} newRange as the new range
   * @return {M.style.Cluster}
   * @api stable
   */
  M.style.Cluster.prototype.updateRange = function(min, max, newRange) {
    this.getImpl().updateRangeImpl(min, max, newRange, this.layer_, this);
    this.unapply(this.layer_);
    this.layer_.setStyle(this);
    return this;
  };

  /**
   * This function set if layer must be animated
   *
   * @function
   * @public
   * @param {boolean} animated defining if layer must be animated
   * @return {M.style.Cluster}
   * @api stable
   */
  M.style.Cluster.prototype.setAnimated = function(animated) {
    return this.getImpl().setAnimated(animated, this.layer_, this);
  };

  /**
   * This function return if layer is animated
   *
   * @function
   * @public
   * @return {boolean} A flag indicating if layer is currently being animated
   * @api stable
   */
  M.style.Cluster.prototype.isAnimated = function() {
    return this.options_.animated;
  };

  /**
   * This function returns data url to canvas
   *
   * @function   * @protected
   * @return {String} data url to canvas
   */
  M.style.Cluster.prototype.toImage = function() {
    let base64Img;
    if (!M.utils.isNullOrEmpty(this.oldStyle_)) {
      base64Img = this.oldStyle_.toImage();
    }
    else {
      base64Img = goog.base(this, 'toImage', this);
    }
    return base64Img;
  };

  /**
   * This function updates the style of the
   * layer
   *
   * @public
   * @function
   * @return {String} data url to canvas
   * @api stable
   */
  M.style.Cluster.prototype.refresh = function() {
    if (!M.utils.isNullOrEmpty(this.layer_)) {
      this.unapply(this.layer_);
      this.apply(this.layer_);
      this.updateCanvas();
    }
  };

  /**
   * Default options for this style
   * @const
   * @type {object}
   * @public
   * @api stable
   */
  M.style.Cluster.DEFAULT = {
    hoverInteraction: true,
    displayAmount: true,
    selectInteraction: true,
    distance: 60,
    animated: true,
    maxFeaturesToSelect: 15,
    label: {
      text: function(feature) {
        let text;
        let cluseterFeatures = feature.getAttribute('features');
        if (!M.utils.isNullOrEmpty(cluseterFeatures)) {
          text = cluseterFeatures.length.toString();
        }
        return text;
      },
      color: '#fff',
      font: "bold 15px Arial",
      baseline: 'middle',
      align: "center"
    }
  };

  /**
   * Default options for this style
   * @const
   * @type {object}
   * @public
   * @api stable
   */
  M.style.Cluster.DEFAULT_VENDOR = {
    animationDuration: 250,
    animationMethod: "linear",
    distanceSelectFeatures: 15,
    convexHullStyle: {
      fill: {
        color: '#fff',
        opacity: 0.25
      },
      stroke: {
        // color: '#425f82'
        color: '#7b98bc'
      }
    }
  };

  /**
   * Default options for range 1 style
   * @const
   * @type {object}
   * @public
   * @api stable
   */
  M.style.Cluster.RANGE_1_DEFAULT = {
    fill: {
      color: '#81c89a'
    },
    stroke: {
      color: '#6eb988',
      width: 3
    },
    radius: 15
  };

  /**
   * Default options for range 2 style
   * @const
   * @type {object}
   * @public
   * @api stable
   */
  M.style.Cluster.RANGE_2_DEFAULT = {
    fill: {
      color: '#85b9d2'
    },
    stroke: {
      color: '#6da4be',
      width: 3
    },
    radius: 20,
  };

  /**
   * Default options for range 3 style
   * @const
   * @type {object}
   * @public
   * @api stable
   */
  M.style.Cluster.RANGE_3_DEFAULT = {
    fill: {
      color: '#938fcf'
    },
    stroke: {
      color: '#827ec5',
      width: 3
    },
    radius: 25
  };
})();