/* Copyright (c) 2015-present The Open Source Geospatial Foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* The permalink provider.
*
* **CAUTION: This class is only usable in applications using the classic
* toolkit of ExtJS 6.**
*
* Sample code displaying a new permalink each time the map is moved:
*
* @example preview
* // create permalink provider
* var permalinkProvider = Ext.create('GeoExt.state.PermalinkProvider', {});
* // set it in the state manager
* Ext.state.Manager.setProvider(permalinkProvider);
*
* // create a map panel, and make it stateful
* var mapComponent = Ext.create('GeoExt.component.Map', {
* stateful: true,
* stateId: 'gx_mapstate',
* map: new ol.Map({
* layers: [
* new ol.layer.Tile({
* source: new ol.source.OSM()
* })
* ],
* view: new ol.View({
* center: ol.proj.fromLonLat([-8.751278, 40.611368]),
* zoom: 12
* })
* })
* });
* var mapPanel = Ext.create('Ext.panel.Panel', {
* title: 'GeoExt.component.Map Example',
* height: 200,
* items: [mapComponent],
* renderTo: Ext.getBody()
* });
* // display permalink hash each time state is changed
* permalinkProvider.on({
* statechange: function(provider, name, value) {
* alert(provider.getPermalinkHash());
* }
* });
*
* @class GeoExt.state.PermalinkProvider
*/
Ext.define('GeoExt.state.PermalinkProvider', {
extend: 'Ext.state.Provider',
requires: [],
alias: 'state.gx_permalinkprovider',
/**
* Current map state object.
*
* @property {Object} mapState Current map state object
* @private
*/
mapState: null,
constructor: function () {
const me = this;
me.callParent(arguments);
if (window.location.hash !== '') {
me.mapState = me.readPermalinkHash(window.location.hash);
}
},
/**
* Create a state object from a URL hash.
* The hash to be in the form `#map=12/-1035528.44/7073659.19/0`
*
* @param {string} plHash The URL hash to get the state from
* @return {Object} The state object
* @private
*/
readPermalinkHash: function (plHash) {
let mapState;
// try to restore center, zoom-level and rotation from the URL
const hash = plHash.replace('#map=', '');
const parts = hash.split('/');
if (parts.length === 4) {
mapState = {
zoom: parseInt(parts[0], 10),
center: [parseFloat(parts[1]), parseFloat(parts[2])],
rotation: parseFloat(parts[3]),
};
}
return mapState;
},
/**
* Returns the URL hash part with current zoom-level, center and rotation
* corresponding to the current state.
*
* @param {boolean} doRound Flag if coords should be rounded to 2
* digits or not
* @return {string} The hash part of the permalink
*/
getPermalinkHash: function (doRound) {
const me = this;
const mapState = me.mapState;
let centerX = mapState.center[0];
let centerY = mapState.center[1];
if (doRound) {
centerX = Math.round(centerX * 100) / 100;
centerY = Math.round(centerY * 100) / 100;
}
const hash =
'#map=' +
mapState.zoom +
'/' +
centerX +
'/' +
centerY +
'/' +
mapState.rotation;
return hash;
},
/**
* Sets the value for a key.
*
* @param {string} name The key name
* @param {Object} value The value to set
*/
set: function (name, value) {
const me = this;
// keep our mapState object in sync with the state
me.mapState = value;
// call 'set' of super class
me.callParent(arguments);
},
});