diff --git a/src/components/App.jsx b/src/components/App.jsx
index 29d5305..e3ddf0d 100644
--- a/src/components/App.jsx
+++ b/src/components/App.jsx
@@ -10,6 +10,7 @@ import Toolbar from './Toolbar'
import AppLayout from './AppLayout'
import MessagePanel from './MessagePanel'
+import { downloadGlyphsMetadata, downloadSpriteMetadata } from '../libs/metadata'
import GlSpec from 'mapbox-gl-style-spec/reference/latest.js'
import validateStyleMin from 'mapbox-gl-style-spec/lib/validate_style.min'
import formatStyle from 'mapbox-gl-style-spec/lib/format'
@@ -21,6 +22,18 @@ import { ApiStyleStore } from '../libs/apistore'
import { RevisionStore } from '../libs/revisions'
import LayerWatcher from '../libs/layerwatcher'
+function updateRootSpec(spec, fieldName, newValues) {
+ return {
+ ...spec,
+ $root: {
+ ...spec.$root,
+ [fieldName]: {
+ ...spec.$root[fieldName],
+ values: newValues
+ }
+ }
+ }
+}
export default class App extends React.Component {
constructor(props) {
@@ -52,6 +65,7 @@ export default class App extends React.Component {
sources: {},
vectorLayers: {},
inspectModeEnabled: false,
+ spec: GlSpec,
}
this.layerWatcher = new LayerWatcher({
@@ -85,7 +99,26 @@ export default class App extends React.Component {
this.styleStore.save(snapshotStyle)
}
+ updateFonts(urlTemplate) {
+ downloadGlyphsMetadata(urlTemplate, fonts => {
+ this.setState({ spec: updateRootSpec(this.state.spec, 'glyphs', fonts)})
+ })
+ }
+
+ updateIcons(baseUrl) {
+ downloadSpriteMetadata(baseUrl, icons => {
+ this.setState({ spec: updateRootSpec(this.state.spec, 'sprite', icons)})
+ })
+ }
+
onStyleChanged(newStyle, save=true) {
+ if(newStyle.glyphs !== this.state.mapStyle.glyphs) {
+ this.updateFonts(newStyle.glyphs)
+ }
+ if(newStyle.sprite !== this.state.mapStyle.sprite) {
+ this.updateIcons(newStyle.sprite)
+ }
+
const errors = validateStyleMin(newStyle, GlSpec)
if(errors.length === 0) {
this.revisionStore.addRevision(newStyle)
@@ -212,6 +245,7 @@ export default class App extends React.Component {
layer={selectedLayer}
sources={this.state.sources}
vectorLayers={this.state.vectorLayers}
+ spec={this.state.spec}
onLayerChanged={this.onLayerChanged.bind(this)}
onLayerIdChange={this.onLayerIdChange.bind(this)}
/> : null
diff --git a/src/components/fields/PropertyGroup.jsx b/src/components/fields/PropertyGroup.jsx
index 2a074b9..90b7b33 100644
--- a/src/components/fields/PropertyGroup.jsx
+++ b/src/components/fields/PropertyGroup.jsx
@@ -1,20 +1,34 @@
import React from 'react'
-import GlSpec from 'mapbox-gl-style-spec/reference/latest.js'
import ZoomSpecField from './ZoomSpecField'
import colors from '../../config/colors'
import { margins } from '../../config/scales'
+const iconProperties = ['background-pattern', 'fill-pattern', 'line-pattern', 'fill-extrusion-pattern', 'icon-image']
+
/** Extract field spec by {@fieldName} from the {@layerType} in the
* style specification from either the paint or layout group */
-function getFieldSpec(layerType, fieldName) {
- const groupName = getGroupName(layerType, fieldName)
- const group = GlSpec[groupName + '_' + layerType]
- return group[fieldName]
+function getFieldSpec(spec, layerType, fieldName) {
+ const groupName = getGroupName(spec, layerType, fieldName)
+ const group = spec[groupName + '_' + layerType]
+ const fieldSpec = group[fieldName]
+ if(iconProperties.indexOf(fieldName) >= 0) {
+ return {
+ ...fieldSpec,
+ values: spec.$root.sprite.values
+ }
+ }
+ if(fieldName === 'text-font') {
+ return {
+ ...fieldSpec,
+ values: spec.$root.glyphs.values
+ }
+ }
+ return fieldSpec
}
-function getGroupName(layerType, fieldName) {
- const paint = GlSpec['paint_' + layerType] || {}
+function getGroupName(spec, layerType, fieldName) {
+ const paint = spec['paint_' + layerType] || {}
if (fieldName in paint) {
return 'paint'
} else {
@@ -27,16 +41,17 @@ export default class PropertyGroup extends React.Component {
layer: React.PropTypes.object.isRequired,
groupFields: React.PropTypes.array.isRequired,
onChange: React.PropTypes.func.isRequired,
+ spec: React.PropTypes.object.isRequired,
}
onPropertyChange(property, newValue) {
- const group = getGroupName(this.props.layer.type, property)
+ const group = getGroupName(this.props.spec, this.props.layer.type, property)
this.props.onChange(group , property, newValue)
}
render() {
const fields = this.props.groupFields.map(fieldName => {
- const fieldSpec = getFieldSpec(this.props.layer.type, fieldName)
+ const fieldSpec = getFieldSpec(this.props.spec, this.props.layer.type, fieldName)
const paint = this.props.layer.paint || {}
const layout = this.props.layer.layout || {}
diff --git a/src/components/fields/SpecField.jsx b/src/components/fields/SpecField.jsx
index 47e1c70..f51d43f 100644
--- a/src/components/fields/SpecField.jsx
+++ b/src/components/fields/SpecField.jsx
@@ -1,7 +1,6 @@
import React from 'react'
import color from 'color'
-import GlSpec from 'mapbox-gl-style-spec/reference/latest.min.js'
import ColorField from './ColorField'
import NumberInput from '../inputs/NumberInput'
import CheckboxInput from '../inputs/CheckboxInput'
@@ -10,8 +9,10 @@ import SelectInput from '../inputs/SelectInput'
import MultiButtonInput from '../inputs/MultiButtonInput'
import ArrayInput from '../inputs/ArrayInput'
import FontInput from '../inputs/FontInput'
+import IconInput from '../inputs/IconInput'
import capitalize from 'lodash.capitalize'
+const iconProperties = ['background-pattern', 'fill-pattern', 'line-pattern', 'fill-extrusion-pattern', 'icon-image']
import input from '../../config/input.js'
@@ -78,11 +79,17 @@ export default class SpecField extends React.Component {
options={options}
/>
}
- case 'string': return (
-
- )
+ case 'string':
+ if(iconProperties.indexOf(this.props.fieldName) >= 0) {
+ return
+ } else {
+ return
+ }
case 'color': return (
} else {
return [f, f])}
+ options={this.props.fonts.map(f => [f, f])}
onChange={this.changeFont.bind(this, i)}
wrapperStyle={{
display: 'block',
diff --git a/src/components/layers/LayerEditor.jsx b/src/components/layers/LayerEditor.jsx
index 1897c02..138ef06 100644
--- a/src/components/layers/LayerEditor.jsx
+++ b/src/components/layers/LayerEditor.jsx
@@ -1,6 +1,5 @@
import React from 'react'
-import GlSpec from 'mapbox-gl-style-spec/reference/latest.js'
import JSONEditor from './JSONEditor'
import FilterEditor from '../filter/FilterEditor'
import PropertyGroup from '../fields/PropertyGroup'
@@ -47,6 +46,7 @@ export default class LayerEditor extends React.Component {
layer: React.PropTypes.object.isRequired,
sources: React.PropTypes.object,
vectorLayers: React.PropTypes.object,
+ spec: React.PropTypes.object.isRequired,
onLayerChanged: React.PropTypes.func,
onLayerIdChange: React.PropTypes.func,
}
@@ -146,6 +146,7 @@ export default class LayerEditor extends React.Component {
case 'properties': return
case 'jsoneditor': return