/*
* Copyright (c) 2013 Bundesamt für 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/Style.js
* @requires OpenLayers/Rule.js
* @requires OpenLayers/StyleMap.js
* @requires OpenLayers/Control/Measure.js
* @requires OpenLayers/Handler/Path.js
* @requires OpenLayers/Handler/Polygon.js
* @requires OpenLayers/Layer/Vector.js
* @requires BKGWebMap/Util.js
* @requires BKGWebMap/Control.js
*/
/**
* @classdesc Tool zum Messen von Entfernungen und Flächen
*
* @constructor BKGWebMap.Control.Measurement
* @param {object} options - Optionen für das Werkzeug
* @param {object} options.styles - Der Visualisierungstil
* @param {HTMLElement} options.target - HTML-Element zur Anzeige der Messwertes
*/
BKGWebMap.Control.Measurement = OpenLayers.Class( OpenLayers.Control, {
/**
* Visualisierung der Messung
* @type object
* @memberOf BKGWebMap.Control.Measurement
*/
styles : null,
/**
* HTML-Element für Moduswahl und Messausgabe
* @type HTMLElement
* @memberOf BKGWebMap.Control.Measurement
*/
target : null,
/**
* Selectbox für Messmodus.
* @type HTMLElement
* @memberOf BKGWebMap.Control.Measurement
*/
modeSelectBox : null,
/**
* HTML-Element zur Anzeige des Messwertes
* @type HTMLElement
* @memberOf BKGWebMap.Control.Measurement
*/
output : null,
/**
* Labels für Beschriftung.
* @type object
* @memberOf BKGWebMap.Control.Measurement
*/
labels : {
line : 'Entfernung',
polygon : 'Fläche'
},
// type: OpenLayers.Control.TYPE_TOGGLE,
type: OpenLayers.Control.TYPE_TOOL,
initialize: function(options) {
options = OpenLayers.Util.applyDefaults(options, { styles: BKGWebMap.Control.Measurement.STYLES.GELB });
// Erweitere Labels, um alle vordefinierten Felder zu erhalten.
if('labels' in options) {
OpenLayers.Util.extend(this.labels, options.labels);
delete options.labels;
}
OpenLayers.Control.prototype.initialize.apply(this, [options]);
// add style for measure tool
var style = new OpenLayers.Style();
style.addRules([new OpenLayers.Rule({symbolizer: this.styles})]);
var styleMap = new OpenLayers.StyleMap({"default": style});
// Kontrollen für Messmodi initiieren
var measureOptions = { persist: true, immediate : true, handlerOptions: {layerOptions: {styleMap: styleMap}}};
this.measureControls = {
line: new OpenLayers.Control.Measure(OpenLayers.Handler.Path, measureOptions),
polygon: new OpenLayers.Control.Measure(OpenLayers.Handler.Polygon, measureOptions)
};
// Messeventhandler registrieren
for(var key in this.measureControls) {
var control = this.measureControls[key];
control.events.on({
measure: this.handleMeasurements,
measurepartial: this.handleMeasurements,
scope: this
});
}
},
draw: function (px) {
var div = OpenLayers.Control.prototype.draw.apply(this, arguments);
if(!this.target) {
this.target = document.createElement('div');
if(this.map) {
this.map.viewPortDiv.appendChild( this.target );
// Damit die Selectbox in der Karte ausgewählt werden kann
OpenLayers.Event.observe( this.target, "mousedown", BKGWebMap.Util.stopEvent );
OpenLayers.Event.observe( this.target, "mouseup", BKGWebMap.Util.stopEvent );
OpenLayers.Event.observe( this.target, "click", BKGWebMap.Util.stopEvent );
}
}
OpenLayers.Element.addClass(this.target, this.displayClass + 'Wrapper');
this.target.style.display = 'none';
// Auswahl für Messmodus
this.modeSelectBox = document.createElement('select');
OpenLayers.Element.addClass(this.modeSelectBox, this.displayClass + 'Select');
this.target.appendChild(this.modeSelectBox);
for(var key in this.measureControls) {
var option = document.createElement('option');
option.innerHTML = this.labels[key];
option.value = key;
this.modeSelectBox.appendChild(option);
}
OpenLayers.Event.observe(this.modeSelectBox, "change", OpenLayers.Function.bindAsEventListener(this.toggleMeasure, this));
// Ausgabebereich für Messwerte
this.output = document.createElement('span');
this.target.appendChild(this.output);
return div;
},
/**
* Fügt zusätzlich Subcontrols hinzu
* @memberOf BKGWebMap.Control.Measurement
* @param {OpenLayers.Map} map
*/
setMap: function(map) {
OpenLayers.Control.prototype.setMap.apply(this, arguments);
for(var key in this.measureControls) {
map.addControl(this.measureControls[key]);
}
// Navigationstool ermitteln. Das soll automatisch aktiviert werden wenn Messen aktiviert wird
var navControls = map.getControlsByClass("OpenLayers.Control.Navigation")
this._navControl = navControls.length > 0 ? navControls[0] : null;
},
/**
* Aktiviert das Messwerkzeug und wählt den Messmodus entsprechend der Auswahl in der SelectBox
* @memberOf BKGWebMap.Control.Measurement
*/
activate: function() {
if (this._navControl) this._navControl.activate();
this.target.style.display = '';
this.toggleMeasure({target: this.modeSelectBox.options[this.modeSelectBox.selectedIndex]});
return OpenLayers.Control.prototype.activate.apply(this, arguments);
},
/**
* Deaktiviert das Messwerkzeug
* @memberOf BKGWebMap.Control.Measurement
*/
deactivate: function() {
this.target.style.display = 'none';
for(var key in this.measureControls) {
var control = this.measureControls[key];
control.deactivate();
}
return OpenLayers.Control.prototype.deactivate.apply(this, arguments);
},
/**
* Reagiert auf Messereignisse und aktualisiert die Anzeige.
*
* @memberOf BKGWebMap.Control.Measurement
* @param {Event} event
*/
handleMeasurements : function(event) {
// var geometry = event.geometry;
var out = "";
if(event.order == 1) {
out += event.measure.toFixed(3) + " " + event.units;
} else {
out += event.measure.toFixed(3) + " " + event.units + "<sup>2</sup>";
}
this.output.innerHTML = out;
},
/**
* Reagiert auf Änderungen in der SelectBox und setzt den gewählten Messmodus
*
* @memberOf BKGWebMap.Control.Measurement
* @param {{target: *}} event
*/
toggleMeasure : function(event) {
var value = event.target.value;
this.output.innerHTML = '';
for(var key in this.measureControls) {
var control = this.measureControls[key];
if(value == key) {
control.activate();
} else {
control.deactivate();
}
}
},
CLASS_NAME: "BKGWebMap.Control.Measurement"
});
/**
* Visualisierungsstile
* @type object
* @constant
*/
BKGWebMap.Control.Measurement.STYLES = BKGWebMap.STYLES;
/**
* Gelber Visualisierungsstil
* @deprecated
* @type object
* @constant
*/
BKGWebMap.Control.Measurement.STYLE_YELLOW = BKGWebMap.Control.Measurement.STYLES.GELB;
/**
* roter Visualisierungsstil
* @deprecated
* @type object
* @constant
*/
BKGWebMap.Control.Measurement.STYLE_RED = BKGWebMap.Control.Measurement.STYLE_YELLOW = BKGWebMap.Control.Measurement.STYLES.ROT;
/**
* Factory-Funktion zur Generierung eines Mesurement Steuerelement.
* @param {Array<OpenLayers.Control>} controls - Liste der Steuerelemente, in die die neue erzeugten Steuerelemente
* eingefügt werden sollen.
* @param {object} config - Konfiguration für Steuerelement (s. Konstruktor BKGWebMap.Control.Measurement)
* @param {object|string} config.styles - Stylekonfiguration oder key aus BKGWebMap.Control.Measurement.STYLES
*/
BKGWebMap.Control.FACTORIES['measure'] = function(controls, config) {
if (!config) return;
config = (typeof config === 'boolean') ? {} : config;
if (config.styles && typeof config.styles === 'string') {
config.styles = BKGWebMap.Control.Measurement.STYLES[config.styles];
}
if (config.target && typeof config.target === 'string') {
config.target = OpenLayers.Util.getElement(config.target);
}
controls.push(new BKGWebMap.Control.Measurement(config));
};