Source: BKGWebMap/MapBuilder.js

/*
 * Copyright (c) 2014 Bundesamt by Kartographie und Geodäsie.
 * See license.txt in the BKG WebMap distribution or repository for the
 * full text of the license.
 *
 * Author: Dirk Thalheim
 */
/**
 * @requires OpenLayers/BaseTypes/Class.js
 * @requires OpenLayers/Util.js
 * @requires OpenLayers/Map.js
 * @requires OpenLayers/Control/ArgParser.js
 * @requires OpenLayers/Control/Attribution.js
 * @requires OpenLayers/Control/Navigation.js
 * @requires BKGWebMap/Constants.js
 * @requires BKGWebMap/Layer.js
 * @requires BKGWebMap/Control.js
 * @requires BKGWebMap/Util.js
 */

/**
 * @classdesc Factory-Klasse zur Erstellung von Kartenanwendungen.
 *
 * Erstellt eine Kartenanwendung anhand der eingestellten Konfigurationen. Zur Konfiguration können
 * die Methoden setLayers(), setControls() und setDiv() verwendet werden. Anschließend lässt sich die
 * Kartenanwendung mit create() erzeugen.
 *
 * @constructor BKGWebMap.MapBuilder
 **/
BKGWebMap.MapBuilder  = OpenLayers.Class({

  /**
   * Standardkonfiguration für Kartenobjekt.
   *
   * @memberOf BKGWebMap.MapBuilder
   * @type object
   */
  DEFAULT_MAP_CONFIG: {
    /**
     * Basisgeoreferenzierung für Kartenobjekt. Default: 'EPSG:25832'
     * @type string
     */
    projection: 'EPSG:25832',
    /**
     * Ausdehnung für Kartenanwendung. Default: Deutschland in UTM32 Koordinaten
     * @type OpenLayers.Bounds
     */
    maxExtent: BKGWebMap.EXTENTS['EPSG:25832'],
    /**
     * Maßeinheiten für Karte. Default: 'm'
     * @type string
     */
    units: 'm',
    /**
     * Name des Layout-Themes. Default: null
     * @type string
     */
    theme: null
  },

  /**
   * Standardkonfiguration für Steuerelemente.
   *
   * @memberOf BKGWebMap.MapBuilder
   * @type object
   */
  DEFAULT_CONTROL_CONFIG: {
    /**
     *  Falls die erweiterte PanZoombar anstelle des einfachen Zooms (+,-) verwendet werden soll, muss dieser
     *  Parameter auf <code>true</code> gesetzt werden.
     * @type boolean
     */
    zoomBar: false,

    /**
     * Falls die Cookies-Einstellungen überprüft werden sollen, kann dieses Attribut auf <code>true</code> gesetzt
     * werden. Ein BKGWebMap.Control.CookieCheck wird dann der Karte hinzugefügt. Cookies werde bei der Verwendung
     * geschützter Dienste benötigt.
     * @type boolean
     */
    checkCookies: false
  },

  /**
   * ID des HTML-Elements welches die Kartenanwendung enthalten soll
   * @memberOf BKGWebMap.MapBuilder
   * @type string
   */
  div: 'map',

  /**
   * Konfiguration der Steuerelemente für die Kartenanwendung.
   *
   * @memberOf BKGWebMap.MapBuilder
   * @type Array<OpenLayers.Control>
   */
  controlsConfig: {},

  /**
   * Konfiguration für Kartenobjekt.
   *
   * @memberOf BKGWebMap.MapBuilder
   * @type object
   */
  mapConfig: null,

  /**
   * Konfiguration der Layer, die der Karte hinzugefügt werden sollen.
   *
   * @memberOf BKGWebMap.MapBuilder
   * @type Array<string|object|OpenLayers.Layer>
   */
  layerConfigs: null,

  initialize: function(options) {
    OpenLayers.Util.extend(this, options);

    this.layerConfigs = [{type: 'BASEMAPDE.FARBE'}];

    this.setControls({});
    this.setMapConfig({});
  },

  /**
   * Setzt das HTML-Element, welches später die Kartenanwendung enthält.
   *
   * @memberOf BKGWebMap.MapBuilder
   * @param {string} div - ID des HTML-Elements welches später die Karte enthält
   * @return {BKGWebMap.MapBuilder}
   */
  setDiv: function(div) {
    this.div = div;
    return this;
  },

  /**
   * Setzt das Konfiguration für die Kartenanwendung.
   *
   * @memberOf BKGWebMap.MapBuilder
   * @param {object} config - Konfiguration für die Kartenanwendung
   * @return {BKGWebMap.MapBuilder}
   */
  setMapConfig: function(config) {
    this.mapConfig = OpenLayers.Util.extend(null, this.DEFAULT_MAP_CONFIG);
    // neue Konfigurationswerte übernehmen
    this.mapConfig = OpenLayers.Util.extend(this.mapConfig, config);

    // Projektionsabhängige Ausdehnung setzen
    if (config.projection && !config.maxExtent) {
      var extent = BKGWebMap.Util.getMaxExtent(config.projection.toUpperCase(), BKGWebMap.EXTENTS);
      if (extent != null) this.mapConfig.maxExtent = extent;
    }

    // richtige Maßeinheit setzen
    if (config.projection && config.projection in BKGWebMap.UNITS) {
      this.mapConfig.units = BKGWebMap.UNITS[config.projection];
    }

    // Setze Zoomstufen in Abhängigkeit der Maßeinheit
    if(!this.mapConfig.resolutions && !this.mapConfig.scales && !this.mapConfig.minScale &&
        !this.mapConfig.maxScale && !this.mapConfig.maxResolution && !this.mapConfig.minResolution &&
        !this.mapConfig.numZoomLevels) {
      if(this.mapConfig.units == 'm') {
        this.mapConfig.resolutions = BKGWebMap.RESOLUTIONS;
      } else if (this.mapConfig.units == 'degree' || this.mapConfig.units == 'dd' ) {
        this.mapConfig.resolutions = BKGWebMap.RESOLUTIONS_DEGREE;
      }
    }

    return this;
  },

  /**
   * Konfiguriert die Layer, die der Kartenanwendung hinzugefügt werden. <br/>
   * Es können direkt OpenLayers.Layer-Instanzen übergeben werden oder Konfigurationsangaben paer JavaScript Objekt.
   * Bei Letzterem wird per type-Attribut die entsprechende Layer-Implementierung verwendet. Details dazu finden sich in
   * der <a href="../factories.html#layer">MapBuilder-Referenz</a>.
   *
   * @memberOf BKGWebMap.MapBuilder
   * @see BKGWebMap.MapBuilder.createLayer
   * @param {Array<object|OpenLayers.Layer>} layerConfigs - Liste mit Layerkonfigurationen oder Layer-Instanzen.
   * @return {BKGWebMap.MapBuilder}
   */
  setLayers: function (layerConfigs) {
    this.layerConfigs = layerConfigs;
    return this;
  },

  /**
   * Konfiguriert die Steuerelemente der Kartenanwendung. <br/>
   * Es wird ein JavaScript Objekt übergeben, das die aktiven Steuerelemente konfiguriert. Über den Attributnamen wird
   * entschieden welches Steuerelement aktiviert wird. Der Attributwert wird zur Konfiguration des Steuerelements
   * verwendet. Details dazu finden sich in der <a href="../factories.html#controls">MapBuilder-Referenz</a>.
   *
   * @memberOf BKGWebMap.MapBuilder
   * @see BKGWebMap.MapBuilder.createLayer
   * @param {object} config
   * @return {BKGWebMap.MapBuilder}
   */
  setControls: function(config) {
    this.controlsConfig = config;
    return this;
  },

  initControls: function (config) {
    var controls = [];

    // Standard Steuerelemente hinzufügen

    // KVP-Argument-Parser
    if (OpenLayers.Control.ArgParser) {
      controls.push(new OpenLayers.Control.ArgParser());
    }
    // Fußnote
    if (OpenLayers.Control.Attribution) {
      controls.push(new OpenLayers.Control.Attribution());
    }

    // Navigation or TouchNavigation depending on what is in build
    if (OpenLayers.Control.Navigation) {
      controls.push(new OpenLayers.Control.Navigation());
    } else if (OpenLayers.Control.TouchNavigation) {
      controls.push(new OpenLayers.Control.TouchNavigation());
    }

    var ctrlConfig = OpenLayers.Util.extend(null, this.DEFAULT_CONTROL_CONFIG);
    ctrlConfig = OpenLayers.Util.extend(ctrlConfig, config);

    controls = BKGWebMap.Control.create(ctrlConfig, controls);

    // TODO: evtl. noch abhängige Steuerelemente verknüpfen (z.B. SidePanel)
    return controls;
  },

  /**
   * Erstellt die Kartenanwendung mit der aktuell eingestellten Konfiguration und gibt das Kartenobjekt zurück.
   * @memberOf BKGWebMap.MapBuilder
   * @return {OpenLayers.Map}
   */
  create: function() {
    var mapConfig = OpenLayers.Util.extend(null, this.mapConfig);
    mapConfig.controls = [];
    var map = new OpenLayers.Map(this.div, mapConfig);

    // Layer hinzufügen
    var layers = BKGWebMap.Util.map(BKGWebMap.Layer.create, this.layerConfigs, map);
    BKGWebMap.Util.each(layers, function(index, layer) {if (layer) map.addLayer(layer);});

    // controls
    map.addControls(this.initControls(this.controlsConfig));

    if (!map.getCenter()) {
      // Zoom auf gesamte Kartenausdehnung
      if(map.layers.length > 0) map.zoomToMaxExtent();
    }

    return map;
  },

  CLASS_NAME: "BKGWebMap.MapBuilder"
});