From 8d7a230a12e7851ae3b3b944ed9956f83c156b94 Mon Sep 17 00:00:00 2001 From: Kevin Wilson Date: Fri, 19 Jul 2019 15:46:35 -0600 Subject: [PATCH 01/28] feat(fillstyle): add fill color/opacity controls BREAKING CHANGE: Adds required argument to os.ui.file.kml.AbstractKMLExporter#createStyle --- src/os/command/feature/featurecolorcmd.js | 9 +- src/os/command/feature/featurefillcolorcmd.js | 119 +++++++ .../command/feature/featurefillopacitycmd.js | 75 +++++ src/os/command/feature/featureopacitycmd.js | 16 +- .../command/feature/featurestrokecolorcmd.js | 123 +++++++ .../feature/featurestrokeopacitycmd.js | 75 +++++ src/os/command/vectorlayercolorcmd.js | 10 + src/os/command/vectorlayerfillcolorcmd.js | 90 +++++ src/os/command/vectorlayerfillopacitycmd.js | 69 ++++ src/os/command/vectorlayeropacitycmd.js | 94 ++++++ src/os/command/vectorlayerstrokecolorcmd.js | 88 +++++ src/os/command/vectorlayerstrokeopacitycmd.js | 69 ++++ src/os/feature/feature.js | 50 +++ src/os/layer/config/abstractlayerconfig.js | 6 + src/os/layer/vector.js | 9 + src/os/metrics/layersmetrics.js | 45 +++ src/os/metrics/metricskeys.js | 9 + src/os/state/v4/baselayerstate.js | 28 ++ src/os/style/style.js | 21 +- src/os/style/stylefield.js | 2 + src/os/ui/featureedit.js | 90 ++++- src/os/ui/file/kml/abstractkmlexporter.js | 24 +- src/os/ui/layer/vectorlayerui.js | 312 +++++++++++++++++- src/os/ui/layer/vectorstylecontrols.js | 15 + .../featureaction/featurestyleaction.js | 25 ++ .../ui/featurestyleactionconfig.js | 165 ++++++++- src/plugin/file/kml/kmlexporter.js | 14 + src/plugin/file/kml/kmlfield.js | 2 + src/plugin/file/kml/kmlnodelayerui.js | 239 +++++++++++++- src/plugin/file/kml/kmltreeexporter.js | 13 + src/plugin/file/kml/ui/kmlnode.js | 8 + src/plugin/places/places.js | 2 + views/layer/vector.html | 2 + views/layer/vectorstylecontrols.html | 108 +++--- views/plugin/kml/kmlnodelayerui.html | 2 + views/windows/featureedit.html | 2 + 36 files changed, 1949 insertions(+), 81 deletions(-) create mode 100644 src/os/command/feature/featurefillcolorcmd.js create mode 100644 src/os/command/feature/featurefillopacitycmd.js create mode 100644 src/os/command/feature/featurestrokecolorcmd.js create mode 100644 src/os/command/feature/featurestrokeopacitycmd.js create mode 100644 src/os/command/vectorlayerfillcolorcmd.js create mode 100644 src/os/command/vectorlayerfillopacitycmd.js create mode 100644 src/os/command/vectorlayeropacitycmd.js create mode 100644 src/os/command/vectorlayerstrokecolorcmd.js create mode 100644 src/os/command/vectorlayerstrokeopacitycmd.js diff --git a/src/os/command/feature/featurecolorcmd.js b/src/os/command/feature/featurecolorcmd.js index 51c581b0f..e00ddbce4 100644 --- a/src/os/command/feature/featurecolorcmd.js +++ b/src/os/command/feature/featurecolorcmd.js @@ -112,14 +112,9 @@ os.command.FeatureColor.prototype.applyLabelValue = function(configs, value) { */ os.command.FeatureColor.prototype.finish = function(configs) { // dispatch the color change event on the source for the histogram - var feature = /** @type {ol.Feature} */ (this.getFeature()); - var source = /** @type {plugin.file.kml.KMLSource} */ (os.feature.getSource(feature)); - var rootNode = source.getRootNode(); - var children = rootNode.getChildren(); + var feature = this.getFeature(); - for (var i = 0; i < children.length; i++) { // update icon color - children[i].dispatchEvent(new os.events.PropertyChangeEvent('icons')); - } + feature.dispatchEvent(new os.events.PropertyChangeEvent('colors')); os.command.FeatureColor.base(this, 'finish', configs); }; diff --git a/src/os/command/feature/featurefillcolorcmd.js b/src/os/command/feature/featurefillcolorcmd.js new file mode 100644 index 000000000..02e9b2a41 --- /dev/null +++ b/src/os/command/feature/featurefillcolorcmd.js @@ -0,0 +1,119 @@ +goog.provide('os.command.FeatureFillColor'); + +goog.require('os.command.AbstractFeatureStyle'); +goog.require('os.events.PropertyChangeEvent'); +goog.require('os.metrics'); + + + +/** + * Changes the fill color of a feature + * @extends {os.command.AbstractFeatureStyle} + * @param {string} layerId + * @param {string} featureId + * @param {Array|string} color + * @param {(Array|string)=} opt_oldColor + * @constructor + */ +os.command.FeatureFillColor = function(layerId, featureId, color, opt_oldColor) { + os.command.FeatureFillColor.base(this, 'constructor', layerId, featureId, color, opt_oldColor); + this.title = 'Change Feature Fill Color'; + this.metricKey = os.metrics.Layer.FEATURE_FILL_COLOR; + + if (!color) { + var feature = this.getFeature(); + var config = /** @type {Object|undefined} */ (feature.get(os.style.StyleType.FEATURE)); + + if (config) { + if (goog.isArray(config)) { + config = config[0]; + } + var configColor = /** @type {Array|string|undefined} */ (os.style.getConfigColor(config)); + + if (configColor) { + color = os.color.toHexString(color); + } + } + } + + // Make sure the value is a string + this.value = os.style.toRgbaString(color); +}; +goog.inherits(os.command.FeatureFillColor, os.command.AbstractFeatureStyle); + + +/** + * @type {string} + * @const + */ +os.command.FeatureFillColor.DEFAULT_COLOR = 'rgba(255,255,255,0)'; + + +/** + * @inheritDoc + */ +os.command.FeatureFillColor.prototype.getOldValue = function() { + var feature = /** @type {ol.Feature} */ (this.getFeature()); + var config = /** @type {Array|Object|undefined} */ (this.getFeatureConfigs(feature)); + if (goog.isArray(config)) { + config = config[0]; + } + + if (config) { + return os.style.getConfigColor(config, false, os.style.StyleField.FILL); + } else { + return os.command.FeatureFillColor.DEFAULT_COLOR; + } +}; + + +/** + * Gets the old label color + * @return {Array|string|undefined} + */ +os.command.FeatureFillColor.prototype.getLabelValue = function() { + var feature = /** @type {ol.Feature} */ (this.getFeature()); + var labelColor = /** @type {Array|string|undefined} */ (feature.get(os.style.StyleField.LABEL_COLOR)); + return labelColor ? labelColor : os.style.DEFAULT_LAYER_COLOR; +}; + + +/** + * @inheritDoc + */ +os.command.FeatureFillColor.prototype.applyValue = function(configs, value) { + var color = os.style.toRgbaString(/** @type {string} */ (value)); + for (var i = 0; i < configs.length; i++) { + os.style.setConfigColor(configs[i], color, [os.style.StyleField.FILL]); + } + + os.command.FeatureFillColor.base(this, 'applyValue', configs, value); +}; + + +/** + * Set the label color + * @param {Object} configs The style config + * @param {string} value The value to apply + */ +os.command.FeatureFillColor.prototype.applyLabelValue = function(configs, value) { + var feature = /** @type {ol.Feature} */ (this.getFeature()); + feature.set(os.style.StyleField.LABEL_COLOR, value); + + for (var i = 0; i < configs.length; i++) { + configs[i][os.style.StyleField.LABEL_COLOR] = value; + } +}; + + +/** + * @inheritDoc + */ +os.command.FeatureFillColor.prototype.finish = function(configs) { + // dispatch the color change event on the source for the histogram + var feature = this.getFeature(); + + feature.dispatchEvent(new os.events.PropertyChangeEvent('colors')); + + os.command.FeatureFillColor.base(this, 'finish', configs); +}; diff --git a/src/os/command/feature/featurefillopacitycmd.js b/src/os/command/feature/featurefillopacitycmd.js new file mode 100644 index 000000000..77808fcb4 --- /dev/null +++ b/src/os/command/feature/featurefillopacitycmd.js @@ -0,0 +1,75 @@ +goog.provide('os.command.FeatureFillOpacity'); + +goog.require('os.command.AbstractFeatureStyle'); +goog.require('os.events.PropertyChangeEvent'); +goog.require('os.metrics'); +goog.require('os.ui'); + + + +/** + * Changes the fill opacity of a feature + * @extends {os.command.AbstractFeatureStyle} + * @param {string} layerId + * @param {string} featureId + * @param {number} opacity + * @param {number=} opt_oldOpacity + * @constructor + */ +os.command.FeatureFillOpacity = function(layerId, featureId, opacity, opt_oldOpacity) { + os.command.FeatureFillOpacity.base(this, 'constructor', layerId, featureId, opacity, opt_oldOpacity); + this.title = 'Change Feature Fill Opacity'; + this.metricKey = os.metrics.Layer.FEATURE_FILL_OPACITY; + + this.value = opacity; +}; +goog.inherits(os.command.FeatureFillOpacity, os.command.AbstractFeatureStyle); + + +/** + * @type {number} + * @const + */ +os.command.FeatureFillOpacity.DEFAULT_OPACITY = 1; + + +/** + * @inheritDoc + */ +os.command.FeatureFillOpacity.prototype.getOldValue = function() { + var feature = this.getFeature(); + var config = /** @type {Array|Object|undefined} */ (this.getFeatureConfigs(feature)); + if (goog.isArray(config)) { + config = config[0]; + } + + return config ? os.style.getConfigOpacityColor(config) : os.command.FeatureFillOpacity.DEFAULT_OPACITY; +}; + + +/** + * @inheritDoc + */ +os.command.FeatureFillOpacity.prototype.applyValue = function(configs, value) { + var color; + for (var i = 0; i < configs.length; i++) { + color = os.style.getConfigColor(configs[i], true, os.style.StyleField.FILL); + color[3] = value; + os.style.setConfigColor(configs[i], color, [os.style.StyleField.FILL]); + } + + os.command.FeatureFillOpacity.base(this, 'applyValue', configs, value); +}; + + +/** + * @inheritDoc + */ +os.command.FeatureFillOpacity.prototype.finish = function(configs) { + // dispatch the color change event on the source for the histogram + var feature = this.getFeature(); + + feature.dispatchEvent(new os.events.PropertyChangeEvent('colors')); + + os.command.FeatureFillOpacity.base(this, 'finish', configs); +}; diff --git a/src/os/command/feature/featureopacitycmd.js b/src/os/command/feature/featureopacitycmd.js index a8fce46c1..4b381096b 100644 --- a/src/os/command/feature/featureopacitycmd.js +++ b/src/os/command/feature/featureopacitycmd.js @@ -1,6 +1,7 @@ goog.provide('os.command.FeatureOpacity'); goog.require('os.command.AbstractFeatureStyle'); +goog.require('os.events.PropertyChangeEvent'); goog.require('os.metrics'); goog.require('os.ui'); @@ -22,7 +23,7 @@ os.command.FeatureOpacity = function(layerId, featureId, opacity, opt_oldOpacity this.metricKey = os.metrics.Layer.FEATURE_OPACITY; if (!opacity) { - var feature = /** @type {ol.Feature} */ (this.getFeature()); + var feature = this.getFeature(); var config = /** @type {Object|undefined} */ (feature.get(os.style.StyleType.FEATURE)); if (config) { @@ -69,3 +70,16 @@ os.command.FeatureOpacity.prototype.applyValue = function(configs, value) { os.command.FeatureOpacity.base(this, 'applyValue', configs, value); }; + + +/** + * @inheritDoc + */ +os.command.FeatureOpacity.prototype.finish = function(configs) { + // dispatch the color change event on the source for the histogram + var feature = this.getFeature(); + + feature.dispatchEvent(new os.events.PropertyChangeEvent('colors')); + + os.command.FeatureOpacity.base(this, 'finish', configs); +}; diff --git a/src/os/command/feature/featurestrokecolorcmd.js b/src/os/command/feature/featurestrokecolorcmd.js new file mode 100644 index 000000000..bb5e9bcda --- /dev/null +++ b/src/os/command/feature/featurestrokecolorcmd.js @@ -0,0 +1,123 @@ +goog.provide('os.command.FeatureStrokeColor'); + +goog.require('os.command.AbstractFeatureStyle'); +goog.require('os.events.PropertyChangeEvent'); +goog.require('os.metrics'); + + + +/** + * Changes the stroke color of a feature + * @extends {os.command.AbstractFeatureStyle} + * @param {string} layerId + * @param {string} featureId + * @param {Array|string} color + * @param {(Array|string)=} opt_oldColor + * @constructor + */ +os.command.FeatureStrokeColor = function(layerId, featureId, color, opt_oldColor) { + os.command.FeatureStrokeColor.base(this, 'constructor', layerId, featureId, color, opt_oldColor); + this.title = 'Change Feature Stroke Color'; + this.metricKey = os.metrics.Layer.FEATURE_STROKE_COLOR; + + if (!color) { + var feature = this.getFeature(); + var config = /** @type {Object|undefined} */ (feature.get(os.style.StyleType.FEATURE)); + + if (config) { + if (goog.isArray(config)) { + config = config[0]; + } + var configColor = /** @type {Array|string|undefined} */ (os.style.getConfigColor(config)); + + if (configColor) { + color = os.color.toHexString(color); + } + } + } + + // Make sure the value is a string + this.value = os.style.toRgbaString(color); +}; +goog.inherits(os.command.FeatureStrokeColor, os.command.AbstractFeatureStyle); + + +/** + * @type {string} + * @const + */ +os.command.FeatureStrokeColor.DEFAULT_COLOR = 'rgba(255,255,255,1)'; + + +/** + * @inheritDoc + */ +os.command.FeatureStrokeColor.prototype.getOldValue = function() { + var feature = /** @type {ol.Feature} */ (this.getFeature()); + var config = /** @type {Array|Object|undefined} */ (this.getFeatureConfigs(feature)); + if (goog.isArray(config)) { + config = config[0]; + } + + if (config) { + return os.style.getConfigColor(config, false, os.style.StyleField.STROKE); + } else { + return os.command.FeatureStrokeColor.DEFAULT_COLOR; + } +}; + + +/** + * Gets the old label color + * @return {Array|string|undefined} + */ +os.command.FeatureStrokeColor.prototype.getLabelValue = function() { + var feature = /** @type {ol.Feature} */ (this.getFeature()); + var labelColor = /** @type {Array|string|undefined} */ (feature.get(os.style.StyleField.LABEL_COLOR)); + return labelColor ? labelColor : os.style.DEFAULT_LAYER_COLOR; +}; + + +/** + * @inheritDoc + */ +os.command.FeatureStrokeColor.prototype.applyValue = function(configs, value) { + var color = os.style.toRgbaString(/** @type {string} */ (value)); + for (var i = 0; i < configs.length; i++) { + os.style.setConfigColor(configs[i], color, [os.style.StyleField.STROKE, os.style.StyleField.IMAGE]); + } + + if (this.oldValue == this.getLabelValue()) { + this.applyLabelValue(configs, value); + } + + os.command.FeatureStrokeColor.base(this, 'applyValue', configs, value); +}; + + +/** + * Set the label color + * @param {Object} configs The style config + * @param {string} value The value to apply + */ +os.command.FeatureStrokeColor.prototype.applyLabelValue = function(configs, value) { + var feature = /** @type {ol.Feature} */ (this.getFeature()); + feature.set(os.style.StyleField.LABEL_COLOR, value); + + for (var i = 0; i < configs.length; i++) { + configs[i][os.style.StyleField.LABEL_COLOR] = value; + } +}; + + +/** + * @inheritDoc + */ +os.command.FeatureStrokeColor.prototype.finish = function(configs) { + // dispatch the color change event on the source for the histogram + var feature = this.getFeature(); + + feature.dispatchEvent(new os.events.PropertyChangeEvent('colors')); + + os.command.FeatureStrokeColor.base(this, 'finish', configs); +}; diff --git a/src/os/command/feature/featurestrokeopacitycmd.js b/src/os/command/feature/featurestrokeopacitycmd.js new file mode 100644 index 000000000..9714f840f --- /dev/null +++ b/src/os/command/feature/featurestrokeopacitycmd.js @@ -0,0 +1,75 @@ +goog.provide('os.command.FeatureStrokeOpacity'); + +goog.require('os.command.AbstractFeatureStyle'); +goog.require('os.events.PropertyChangeEvent'); +goog.require('os.metrics'); +goog.require('os.ui'); + + + +/** + * Changes the stroke opacity of a feature + * @extends {os.command.AbstractFeatureStyle} + * @param {string} layerId + * @param {string} featureId + * @param {number} opacity + * @param {number=} opt_oldOpacity + * @constructor + */ +os.command.FeatureStrokeOpacity = function(layerId, featureId, opacity, opt_oldOpacity) { + os.command.FeatureStrokeOpacity.base(this, 'constructor', layerId, featureId, opacity, opt_oldOpacity); + this.title = 'Change Feature Stroke Opacity'; + this.metricKey = os.metrics.Layer.FEATURE_STROKE_OPACITY; + + if (!opacity) { + var feature = this.getFeature(); + var config = /** @type {Object|undefined} */ (feature.get(os.style.StyleType.FEATURE)); + + if (config) { + if (goog.isArray(config)) { + config = config[0]; + } + opacity = /** @type {number} */ (os.style.getConfigOpacityColor(config)); + } + } + + this.value = opacity; +}; +goog.inherits(os.command.FeatureStrokeOpacity, os.command.AbstractFeatureStyle); + + +/** + * @type {number} + * @const + */ +os.command.FeatureStrokeOpacity.DEFAULT_OPACITY = 1; + + +/** + * @inheritDoc + */ +os.command.FeatureStrokeOpacity.prototype.getOldValue = function() { + var feature = /** @type {ol.Feature} */ (this.getFeature()); + var config = /** @type {Array|Object|undefined} */ (this.getFeatureConfigs(feature)); + if (goog.isArray(config)) { + config = config[0]; + } + + return config ? os.style.getConfigOpacityColor(config) : os.command.FeatureStrokeOpacity.DEFAULT_OPACITY; +}; + + +/** + * @inheritDoc + */ +os.command.FeatureStrokeOpacity.prototype.applyValue = function(configs, value) { + var color; + + for (var i = 0; i < configs.length; i++) { + color = os.style.getConfigColor(configs[i], true, os.style.StyleField.STROKE); + color[3] = value; + os.style.setConfigColor(configs[i], color, [os.style.StyleField.STROKE, os.style.StyleField.IMAGE]); + } + + os.command.FeatureStrokeOpacity.base(this, 'applyValue', configs, value); +}; diff --git a/src/os/command/vectorlayercolorcmd.js b/src/os/command/vectorlayercolorcmd.js index 3661a95dd..b1e3ac39f 100644 --- a/src/os/command/vectorlayercolorcmd.js +++ b/src/os/command/vectorlayercolorcmd.js @@ -59,6 +59,16 @@ os.command.VectorLayerColor.prototype.getOldValue = function() { os.command.VectorLayerColor.prototype.applyValue = function(config, value) { var color = os.style.toRgbaString(/** @type {string} */ (value)); os.style.setConfigColor(config, color); + + // Make sure the fill color and opacity are updated as well + if (config['fillColor']) { + config['fillColor'] = color; + } + if (config['fillOpacity'] !== undefined) { + var colorArray = os.color.toRgbArray(value); + config['fillOpacity'] = colorArray[3]; + } + os.ui.adjustIconSet(this.layerId, color); os.command.VectorLayerColor.base(this, 'applyValue', config, value); diff --git a/src/os/command/vectorlayerfillcolorcmd.js b/src/os/command/vectorlayerfillcolorcmd.js new file mode 100644 index 000000000..98e4dc269 --- /dev/null +++ b/src/os/command/vectorlayerfillcolorcmd.js @@ -0,0 +1,90 @@ +goog.provide('os.command.VectorLayerFillColor'); + +goog.require('os.command.AbstractVectorStyle'); +goog.require('os.data.OSDataManager'); +goog.require('os.events.PropertyChangeEvent'); +goog.require('os.metrics'); +goog.require('os.source.PropertyChange'); +goog.require('os.ui'); + + + +/** + * Changes the fill color of a layer + * @extends {os.command.AbstractVectorStyle} + * @param {string} layerId + * @param {Array|string} color + * @param {(Array|string)=} opt_oldColor + * @constructor + */ +os.command.VectorLayerFillColor = function(layerId, color, opt_oldColor) { + os.command.VectorLayerFillColor.base(this, 'constructor', layerId, color, opt_oldColor); + this.title = 'Change Fill Color'; + this.metricKey = os.metrics.Layer.VECTOR_FILL_COLOR; + + if (!color) { + var layer = /** @type {os.layer.Vector} */ (os.MapContainer.getInstance().getLayer(this.layerId)); + if (layer) { + var options = layer.getLayerOptions(); + color = /** @type {string} */ (options && options['baseColor'] || os.command.VectorLayerFillColor.DEFAULT_COLOR); + } + } + + // make sure the value is a string + this.value = os.style.toRgbaString(color); +}; +goog.inherits(os.command.VectorLayerFillColor, os.command.AbstractVectorStyle); + + +/** + * @type {string} + * @const + */ +os.command.VectorLayerFillColor.DEFAULT_COLOR = 'rgba(255,255,255,0)'; + + +/** + * @inheritDoc + */ +os.command.VectorLayerFillColor.prototype.getOldValue = function() { + var config = os.style.StyleManager.getInstance().getLayerConfig(this.layerId); + + if (config) { + os.style.getConfigColor(config, false, os.style.StyleField.FILL); + } else { + return os.command.VectorLayerFillColor.DEFAULT_COLOR; + } +}; + + +/** + * @inheritDoc + */ +os.command.VectorLayerFillColor.prototype.applyValue = function(config, value) { + var color = os.style.toRgbaString(/** @type {string} */ (value)); + os.style.setConfigColor(config, color, [os.style.StyleField.FILL]); + + // Make sure the fill color and opacity are updated as well + if (config['fillColor']) { + config['fillColor'] = color; + } + + os.command.VectorLayerFillColor.base(this, 'applyValue', config, value); +}; + + +/** + * @inheritDoc + */ +os.command.VectorLayerFillColor.prototype.finish = function(config) { + // dispatch the color change event on the source for the histogram + var source = os.osDataManager.getSource(this.layerId); + source.dispatchEvent(new os.events.PropertyChangeEvent(os.source.PropertyChange.COLOR, this.value)); + + if (source instanceof os.source.Vector) { + // a color change on the layer should clear any color model on the source + source.setColorModel(null); + } + + os.command.VectorLayerFillColor.base(this, 'finish', config); +}; diff --git a/src/os/command/vectorlayerfillopacitycmd.js b/src/os/command/vectorlayerfillopacitycmd.js new file mode 100644 index 000000000..e229852a3 --- /dev/null +++ b/src/os/command/vectorlayerfillopacitycmd.js @@ -0,0 +1,69 @@ +goog.provide('os.command.VectorLayerFillOpacity'); + +goog.require('os.command.AbstractVectorStyle'); +goog.require('os.events.PropertyChangeEvent'); +goog.require('os.metrics'); +goog.require('os.ui'); + + + +/** + * Changes the fill opacity of a feature + * @extends {os.command.AbstractVectorStyle} + * @param {string} layerId + * @param {number} opacity + * @param {number=} opt_oldOpacity + * @constructor + */ +os.command.VectorLayerFillOpacity = function(layerId, opacity, opt_oldOpacity) { + os.command.VectorLayerFillOpacity.base(this, 'constructor', layerId, opacity, opt_oldOpacity); + this.title = 'Change Fill Opacity'; + this.metricKey = os.metrics.Layer.VECTOR_FILL_OPACITY; + + this.value = opacity; +}; +goog.inherits(os.command.VectorLayerFillOpacity, os.command.AbstractVectorStyle); + + +/** + * @type {number} + * @const + */ +os.command.VectorLayerFillOpacity.DEFAULT_OPACITY = 0; + + +/** + * @inheritDoc + */ +os.command.VectorLayerFillOpacity.prototype.getOldValue = function() { + var config = os.style.StyleManager.getInstance().getLayerConfig(this.layerId); + return config ? os.style.getConfigOpacityColor(config) : os.command.VectorLayerFillOpacity.DEFAULT_OPACITY; +}; + + +/** + * @inheritDoc + */ +os.command.VectorLayerFillOpacity.prototype.applyValue = function(config, value) { + var color = os.style.getConfigColor(config, true, os.style.StyleField.FILL); + color[3] = value; + + var colorString = os.style.toRgbaString(color); + os.style.setConfigColor(config, colorString, [os.style.StyleField.FILL]); + config['fillColor'] = colorString; + config['fillOpacity'] = value; + + os.command.VectorLayerFillOpacity.base(this, 'applyValue', config, value); +}; + + +/** + * @inheritDoc + */ +os.command.VectorLayerFillOpacity.prototype.finish = function(config) { + // dispatch the color change event on the source for the histogram + var source = os.osDataManager.getSource(this.layerId); + source.dispatchEvent(new os.events.PropertyChangeEvent(os.source.PropertyChange.COLOR, this.value)); + + os.command.VectorLayerFillOpacity.base(this, 'finish', config); +}; diff --git a/src/os/command/vectorlayeropacitycmd.js b/src/os/command/vectorlayeropacitycmd.js new file mode 100644 index 000000000..9ac1d28e0 --- /dev/null +++ b/src/os/command/vectorlayeropacitycmd.js @@ -0,0 +1,94 @@ +goog.provide('os.command.VectorLayerOpacity'); + +goog.require('os.command.AbstractVectorStyle'); +goog.require('os.data.OSDataManager'); +goog.require('os.events.PropertyChangeEvent'); +goog.require('os.metrics'); +goog.require('os.source.PropertyChange'); +goog.require('os.ui'); + + + +/** + * Changes the color of a layer + * + * @extends {os.command.AbstractVectorStyle} + * @param {string} layerId + * @param {number} opacity + * @param {number=} opt_oldOpacity + * @constructor + */ +os.command.VectorLayerOpacity = function(layerId, opacity, opt_oldOpacity) { + os.command.VectorLayerOpacity.base(this, 'constructor', layerId, opacity, opt_oldOpacity); + this.title = 'Change Opacity'; + this.metricKey = os.metrics.Layer.VECTOR_OPACITY; + + if (!opacity) { + opacity = os.command.VectorLayerOpacity.DEFAULT_OPACITY; + var layer = /** @type {os.layer.Vector} */ (os.MapContainer.getInstance().getLayer(this.layerId)); + if (layer) { + var options = layer.getLayerOptions(); + if (options && options['baseOpacity']) { + opacity = /** @type {number} */ (options['baseOpacity']); + } + } + } +}; +goog.inherits(os.command.VectorLayerOpacity, os.command.AbstractVectorStyle); + + +/** + * @type {number} + * @const + */ +os.command.VectorLayerOpacity.DEFAULT_OPACITY = 1; + + +/** + * @inheritDoc + */ +os.command.VectorLayerOpacity.prototype.getOldValue = function() { + var config = os.style.StyleManager.getInstance().getLayerConfig(this.layerId); + return config ? os.style.getConfigColor(config) : os.command.VectorLayerOpacity.DEFAULT_OPACITY; +}; + + +/** + * @inheritDoc + */ +os.command.VectorLayerOpacity.prototype.applyValue = function(config, value) { + var color = os.style.getConfigColor(config, true); + color[3] = value; + + var colorString = os.style.toRgbaString(color); + os.style.setConfigColor(config, colorString); + + // Make sure the fill color and opacity are updated as well + if (config['fillColor']) { + config['fillColor'] = colorString; + } + if (config['fillOpacity'] !== undefined) { + config['fillOpacity'] = value; + } + + os.ui.adjustIconSet(this.layerId, color); + + os.command.VectorLayerOpacity.base(this, 'applyValue', config, value); +}; + + +/** + * @inheritDoc + */ +os.command.VectorLayerOpacity.prototype.finish = function(config) { + // dispatch the color change event on the source for the histogram + var source = os.osDataManager.getSource(this.layerId); + source.dispatchEvent(new os.events.PropertyChangeEvent(os.source.PropertyChange.COLOR, this.value)); + + if (source instanceof os.source.Vector) { + // a color change on the layer should clear any color model on the source + source.setColorModel(null); + } + + os.command.VectorLayerOpacity.base(this, 'finish', config); +}; diff --git a/src/os/command/vectorlayerstrokecolorcmd.js b/src/os/command/vectorlayerstrokecolorcmd.js new file mode 100644 index 000000000..ad86835be --- /dev/null +++ b/src/os/command/vectorlayerstrokecolorcmd.js @@ -0,0 +1,88 @@ +goog.provide('os.command.VectorLayerStrokeColor'); + +goog.require('os.command.AbstractVectorStyle'); +goog.require('os.data.OSDataManager'); +goog.require('os.events.PropertyChangeEvent'); +goog.require('os.metrics'); +goog.require('os.source.PropertyChange'); +goog.require('os.ui'); + + + +/** + * Changes the stroke color of a layer + * @extends {os.command.AbstractVectorStyle} + * @param {string} layerId + * @param {Array|string} color + * @param {(Array|string)=} opt_oldColor + * @constructor + */ +os.command.VectorLayerStrokeColor = function(layerId, color, opt_oldColor) { + os.command.VectorLayerStrokeColor.base(this, 'constructor', layerId, color, opt_oldColor); + this.title = 'Change Stroke Color'; + this.metricKey = os.metrics.Layer.VECTOR_STROKE_COLOR; + + if (!color) { + var layer = /** @type {os.layer.Vector} */ (os.MapContainer.getInstance().getLayer(this.layerId)); + if (layer) { + var options = layer.getLayerOptions(); + color = /** @type {string} */ (options && options['baseColor'] || + os.command.VectorLayerStrokeColor.DEFAULT_COLOR); + } + } + + // make sure the value is a string + this.value = os.style.toRgbaString(color); +}; +goog.inherits(os.command.VectorLayerStrokeColor, os.command.AbstractVectorStyle); + + +/** + * @type {string} + * @const + */ +os.command.VectorLayerStrokeColor.DEFAULT_COLOR = 'rgba(255,255,255,1)'; + + +/** + * @inheritDoc + */ +os.command.VectorLayerStrokeColor.prototype.getOldValue = function() { + var config = os.style.StyleManager.getInstance().getLayerConfig(this.layerId); + + if (config) { + os.style.getConfigColor(config, false, os.style.StyleField.STROKE); + } else { + return os.command.VectorLayerFillColor.DEFAULT_COLOR; + } +}; + + +/** + * @inheritDoc + */ +os.command.VectorLayerStrokeColor.prototype.applyValue = function(config, value) { + var color = os.style.toRgbaString(/** @type {string} */ (value)); + + os.style.setConfigColor(config, color, [os.style.StyleField.STROKE, os.style.StyleField.IMAGE]); + os.ui.adjustIconSet(this.layerId, color); + + os.command.VectorLayerStrokeColor.base(this, 'applyValue', config, value); +}; + + +/** + * @inheritDoc + */ +os.command.VectorLayerStrokeColor.prototype.finish = function(config) { + // dispatch the color change event on the source for the histogram + var source = os.osDataManager.getSource(this.layerId); + source.dispatchEvent(new os.events.PropertyChangeEvent(os.source.PropertyChange.COLOR, this.value)); + + if (source instanceof os.source.Vector) { + // a color change on the layer should clear any color model on the source + source.setColorModel(null); + } + + os.command.VectorLayerStrokeColor.base(this, 'finish', config); +}; diff --git a/src/os/command/vectorlayerstrokeopacitycmd.js b/src/os/command/vectorlayerstrokeopacitycmd.js new file mode 100644 index 000000000..293b10be3 --- /dev/null +++ b/src/os/command/vectorlayerstrokeopacitycmd.js @@ -0,0 +1,69 @@ +goog.provide('os.command.VectorLayerStrokeOpacity'); + +goog.require('os.command.AbstractVectorStyle'); +goog.require('os.events.PropertyChangeEvent'); +goog.require('os.metrics'); +goog.require('os.ui'); + + + +/** + * Changes the stroke opacity of a feature + * @extends {os.command.AbstractVectorStyle} + * @param {string} layerId + * @param {number} opacity + * @param {number=} opt_oldOpacity + * @constructor + */ +os.command.VectorLayerStrokeOpacity = function(layerId, opacity, opt_oldOpacity) { + os.command.VectorLayerStrokeOpacity.base(this, 'constructor', layerId, opacity, opt_oldOpacity); + this.title = 'Change Stroke Opacity'; + this.metricKey = os.metrics.Layer.VECTOR_STROKE_OPACITY; + + this.value = opacity; +}; +goog.inherits(os.command.VectorLayerStrokeOpacity, os.command.AbstractVectorStyle); + + +/** + * @type {number} + * @const + */ +os.command.VectorLayerStrokeOpacity.DEFAULT_OPACITY = 1; + + +/** + * @inheritDoc + */ +os.command.VectorLayerStrokeOpacity.prototype.getOldValue = function() { + var config = os.style.StyleManager.getInstance().getLayerConfig(this.layerId); + return config ? os.style.getConfigOpacityColor(config) : os.command.VectorLayerStrokeOpacity.DEFAULT_OPACITY; +}; + + +/** + * @inheritDoc + */ +os.command.VectorLayerStrokeOpacity.prototype.applyValue = function(config, value) { + var color = os.style.getConfigColor(config, true, os.style.StyleField.IMAGE); + color[3] = value; + + var colorString = os.style.toRgbaString(color); + os.style.setConfigColor(config, colorString, [os.style.StyleField.IMAGE, os.style.StyleField.STROKE]); + + os.ui.adjustIconSet(this.layerId, color); + + os.command.VectorLayerStrokeOpacity.base(this, 'applyValue', config, value); +}; + + +/** + * @inheritDoc + */ +os.command.VectorLayerStrokeOpacity.prototype.finish = function(config) { + // dispatch the color change event on the source for the histogram + var source = os.osDataManager.getSource(this.layerId); + source.dispatchEvent(new os.events.PropertyChangeEvent(os.source.PropertyChange.COLOR, this.value)); + + os.command.VectorLayerStrokeOpacity.base(this, 'finish', config); +}; diff --git a/src/os/feature/feature.js b/src/os/feature/feature.js index db2e695be..0f7d92019 100644 --- a/src/os/feature/feature.js +++ b/src/os/feature/feature.js @@ -783,6 +783,56 @@ os.feature.getColor = function(feature, opt_source, opt_default) { }; +/** + * Get the fill color of a feature. + * @param {ol.Feature} feature The feature. + * @param {os.source.ISource=} opt_source The source containing the feature, or null to ignore source color. + * @param {*=} opt_default The default color. + * @return {*} The color. + * + * @suppress {accessControls} To allow direct access to feature metadata. + */ +os.feature.getFillColor = function(feature, opt_source, opt_default) { + if (feature) { + var color = /** @type {string|undefined} */ (feature.values_[os.data.RecordField.COLOR]); + + if (!color) { + // check the layer config to see if it's replacing feature styles + var layerConfig = os.style.getLayerConfig(feature); + if (layerConfig && layerConfig[os.style.StyleField.REPLACE_STYLE]) { + color = /** @type {string|undefined} */ (os.style.getConfigColor(layerConfig, false, os.style.StyleField.FILL)); + } + } + + if (!color) { + var featureConfig = /** @type {Array|Object|undefined} */ (feature.values_[os.style.StyleType.FEATURE]); + if (featureConfig) { + if (Array.isArray(featureConfig)) { + for (var i = 0; !color && i < featureConfig.length; i++) { + color = os.style.getConfigColor(featureConfig[i], false, os.style.StyleField.FILL) || undefined; + } + } else { + color = os.style.getConfigColor(featureConfig, false, os.style.StyleField.FILL) || undefined; + } + } + } + + if (color) { + return color; + } else if (opt_source) { + return opt_source.getColor(); + } else if (opt_source !== null) { + var source = os.feature.getSource(feature); + if (source) { + return source.getColor(); + } + } + } + + return opt_default !== undefined ? opt_default : os.style.DEFAULT_LAYER_COLOR; +}; + + /** * Gets the shape name for a feature. * diff --git a/src/os/layer/config/abstractlayerconfig.js b/src/os/layer/config/abstractlayerconfig.js index 6e9908df9..421ba6c3d 100644 --- a/src/os/layer/config/abstractlayerconfig.js +++ b/src/os/layer/config/abstractlayerconfig.js @@ -26,6 +26,12 @@ os.layer.config.AbstractLayerConfig = function() { */ this.color = os.style.DEFAULT_LAYER_COLOR; + /** + * @type {Array|string} + * @protected + */ + this.fillColor = 'rgba(255,255,255,0)'; + /** * @type {Array} * @protected diff --git a/src/os/layer/vector.js b/src/os/layer/vector.js index 15680ac49..dc8b5198a 100644 --- a/src/os/layer/vector.js +++ b/src/os/layer/vector.js @@ -1163,6 +1163,8 @@ os.layer.Vector.prototype.persist = function(opt_to) { opt_to[os.style.StyleField.LOB_BEARING_COLUMN] = config[os.style.StyleField.LOB_BEARING_COLUMN]; opt_to[os.style.StyleField.LOB_BEARING_ERROR] = config[os.style.StyleField.LOB_BEARING_ERROR]; opt_to[os.style.StyleField.LOB_BEARING_ERROR_COLUMN] = config[os.style.StyleField.LOB_BEARING_ERROR_COLUMN]; + opt_to[os.style.StyleField.FILL_COLOR] = os.style.getConfigColor(config, false, os.style.StyleField.FILL); + opt_to[os.style.StyleField.FILL_OPACITY] = config[os.style.StyleField.FILL_OPACITY]; opt_to[os.style.StyleField.ROTATION_COLUMN] = config[os.style.StyleField.ROTATION_COLUMN]; opt_to[os.style.StyleField.SHOW_ROTATION] = config[os.style.StyleField.SHOW_ROTATION]; opt_to[os.style.StyleField.SHOW_ARROW] = config[os.style.StyleField.SHOW_ARROW]; @@ -1240,6 +1242,11 @@ os.layer.Vector.prototype.restore = function(config) { os.style.setConfigColor(styleConf, os.style.toRgbaString(config[os.style.StyleField.COLOR])); } + if (config[os.style.StyleField.FILL_COLOR] != null) { + var fillString = os.style.toRgbaString(config[os.style.StyleField.FILL_COLOR]); + os.style.setConfigColor(styleConf, fillString, [os.style.StyleField.FILL]); + } + if (config[os.style.StyleField.REPLACE_STYLE] != null) { styleConf[os.style.StyleField.REPLACE_STYLE] = config[os.style.StyleField.REPLACE_STYLE]; } @@ -1282,6 +1289,8 @@ os.layer.Vector.prototype.restore = function(config) { styleConf[os.style.StyleField.ARROW_SIZE] = config[os.style.StyleField.ARROW_SIZE] || os.style.DEFAULT_ARROW_SIZE; styleConf[os.style.StyleField.ARROW_UNITS] = config[os.style.StyleField.ARROW_UNITS] || os.style.DEFAULT_UNITS; + styleConf[os.style.StyleField.FILL_COLOR] = config[os.style.StyleField.FILL_COLOR] || os.style.DEFAULT_FILL_COLOR; + styleConf[os.style.StyleField.FILL_OPACITY] = config[os.style.StyleField.FILL_OPACITY] || os.style.DEFAULT_FILL_ALPHA; styleConf[os.style.StyleField.LOB_COLUMN_LENGTH] = config[os.style.StyleField.LOB_COLUMN_LENGTH] || os.style.DEFAULT_LOB_LENGTH; styleConf[os.style.StyleField.LOB_LENGTH] = config[os.style.StyleField.LOB_LENGTH] || os.style.DEFAULT_LOB_LENGTH; diff --git a/src/os/metrics/layersmetrics.js b/src/os/metrics/layersmetrics.js index a189250f2..0abf03758 100644 --- a/src/os/metrics/layersmetrics.js +++ b/src/os/metrics/layersmetrics.js @@ -33,6 +33,16 @@ os.metrics.LayersMetrics = function() { description: 'The color used to render the data for this layer.', key: os.metrics.Layer.VECTOR_COLOR }); + this.addChild(styleLeaf, { + label: 'Change Feature Layer Stroke Color', + description: 'The stroke color used to render the data for this layer.', + key: os.metrics.Layer.VECTOR_STROKE_COLOR + }); + this.addChild(styleLeaf, { + label: 'Change Feature Layer Fill Color', + description: 'The fill color used to render the data for this layer.', + key: os.metrics.Layer.VECTOR_FILL_COLOR + }); this.addChild(styleLeaf, { label: 'Change Feature Layer Shape', description: 'The icon shape used for data points on this layer.', @@ -53,6 +63,21 @@ os.metrics.LayersMetrics = function() { description: 'The icon size used for data points on this layer.', key: os.metrics.Layer.VECTOR_SIZE }); + this.addChild(styleLeaf, { + label: 'Change Feature Layer Opacity', + description: 'The opacity used to render the data for this layer.', + key: os.metrics.Layer.VECTOR_OPACITY + }); + this.addChild(styleLeaf, { + label: 'Change Feature Layer Fill Opacity', + description: 'The fill opacity used to render the data for this layer.', + key: os.metrics.Layer.VECTOR_FILL_OPACITY + }); + this.addChild(styleLeaf, { + label: 'Change Feature Layer Stroke Opacity', + description: 'The stroke opacity used to render the data for this layer.', + key: os.metrics.Layer.VECTOR_STROKE_OPACITY + }); this.addChild(styleLeaf, { label: 'Change Feature Layer Line Dash', description: 'The line dash for polygons and lines on this layer.', @@ -168,6 +193,16 @@ os.metrics.LayersMetrics = function() { description: 'The color used to render the data for this feature.', key: os.metrics.Layer.FEATURE_COLOR }); + this.addChild(styleLeaf, { + label: 'Change Feature Stroke Color', + description: 'The stroke color used to render the data for this feature.', + key: os.metrics.Layer.FEATURE_STROKE_COLOR + }); + this.addChild(styleLeaf, { + label: 'Change Feature Fill Color', + description: 'The fill color used to render the data for this feature.', + key: os.metrics.Layer.FEATURE_FILL_COLOR + }); this.addChild(styleLeaf, { label: 'Change Feature Icon', description: 'The icon used for data points on this feature.', @@ -178,6 +213,16 @@ os.metrics.LayersMetrics = function() { description: 'The opacity used to render the data for this feature.', key: os.metrics.Layer.FEATURE_OPACITY }); + this.addChild(styleLeaf, { + label: 'Change Feature Stroke Opacity', + description: 'The stroke opacity used to render the data for this feature.', + key: os.metrics.Layer.FEATURE_STROKE_OPACITY + }); + this.addChild(styleLeaf, { + label: 'Change Feature Fill Opacity', + description: 'The fill opacity used to render the data for this feature.', + key: os.metrics.Layer.FEATURE_FILL_OPACITY + }); this.addChild(styleLeaf, { label: 'Change Feature Layer Size', description: 'The icon size used for data points on this feature.', diff --git a/src/os/metrics/metricskeys.js b/src/os/metrics/metricskeys.js index 084df8a1e..03763dc8a 100644 --- a/src/os/metrics/metricskeys.js +++ b/src/os/metrics/metricskeys.js @@ -237,10 +237,15 @@ os.metrics.keys.OS = { os.metrics.Layer = { FORCE_LAYER_COLOR: 'layers.features.forceLayerColor', VECTOR_COLOR: 'layers.features.changeVectorColor', + VECTOR_STROKE_COLOR: 'layers.features.changeVectorStrokeColor', + VECTOR_FILL_COLOR: 'layers.features.changeVectorFillColor', VECTOR_ICON: 'layers.features.changeVectorIcon', VECTOR_SHAPE: 'layers.features.changeVectorShape', VECTOR_CENTER_SHAPE: 'layers.features.changeVectorCenterShape', VECTOR_SIZE: 'layers.features.changeVectorSize', + VECTOR_OPACITY: 'layers.features.changeVectorOpacity', + VECTOR_FILL_OPACITY: 'layers.features.changeVectorFillOpacity', + VECTOR_STROKE_OPACITY: 'layers.features.changeVectorStrokeOpacity', VECTOR_LINE_DASH: 'layers.features.changeVectorLineDash', VECTOR_AUTO_REFRESH: 'layers.features.changeVectorAutoRefresh', VECTOR_ELLIPSOID: 'layers.features.changeVectorEllipsoid', @@ -264,8 +269,12 @@ os.metrics.Layer = { VECTOR_LOB_BEARING_ERROR_COLUMN: 'layers.features.changeVectorLineOfBearingBearingErrorColumn', VECTOR_ROTATION_COLUMN: 'layers.features.changeVectorRotationColumn', FEATURE_COLOR: 'layers.features.changeFeatureColor', + FEATURE_STROKE_COLOR: 'layers.features.changeFeatureStrokeColor', + FEATURE_FILL_COLOR: 'layers.features.changeFeatureFillColor', FEATURE_ICON: 'layers.features.changeFeatureIcon', FEATURE_OPACITY: 'layers.features.changeFeatureOpacity', + FEATURE_STROKE_OPACITY: 'layers.features.changeFeatureStrokeOpacity', + FEATURE_FILL_OPACITY: 'layers.features.changeFeatureFillOpacity', FEATURE_SIZE: 'layers.features.changeFeatureSize', FEATURE_LINE_DASH: 'layers.features.changeFeatureLineDash', FEATURE_LABEL_COLOR: 'layers.features.changeFeatureLabelColor', diff --git a/src/os/state/v4/baselayerstate.js b/src/os/state/v4/baselayerstate.js index 821c846d0..86b20bddb 100644 --- a/src/os/state/v4/baselayerstate.js +++ b/src/os/state/v4/baselayerstate.js @@ -42,6 +42,8 @@ os.state.v4.LayerTag = { CSV_USE_HEADER: 'useHeader', DATA_PROVIDER: 'dataProvider', IS_BASE_LAYER: 'isBaseLayer', + FILL_COLOR: 'fillColor', + FILL_OPACITY: 'fillOpacity', LABEL_COLUMN: 'labelColumn', LABEL_COLUMNS: 'labelColumns', LABEL: 'label', @@ -470,6 +472,16 @@ os.state.v4.BaseLayerState.prototype.configKeyToXML = function(layerConfig, type this.defaultConfigToXML(key, value, layerEl); } break; + case os.style.StyleField.FILL_COLOR: + if (bfs) { + // hex string without the leading hash + var fillColor = os.color.toServerString(/** @type {string} */ (value)); + os.xml.appendElement(os.state.v4.LayerTag.FILL_COLOR, bfs, fillColor); + } else { + // tile layer + this.defaultConfigToXML(key, value, layerEl); + } + break; case 'contrast': if (typeof value === 'number' && !isNaN(value)) { // Cesium contrast: 0 is gray, 1 is normal, > 1 increases contrast. we allow from 0 to 2. @@ -493,6 +505,22 @@ os.state.v4.BaseLayerState.prototype.configKeyToXML = function(layerConfig, type os.xml.appendElement(os.state.v4.LayerTag.ALPHA, layerEl, value); } break; + case os.style.StyleField.FILL_OPACITY: + if (bfs) { + value = value != null ? Number(value) : os.style.DEFAULT_FILL_ALPHA; + var opacity = Math.round(value * 255); + var fillOpacityElement = bfs.querySelector(os.state.v4.LayerTag.FILL_OPACITY); + if (fillOpacityElement) { + fillOpacityElement.textContent = opacity; + } else { + os.xml.appendElement(os.state.v4.LayerTag.FILL_OPACITY, bfs, opacity); + } + } else { + // write tile layer opacity/alpha as alpha + value = value != null ? Number(value) : os.style.DEFAULT_FILL_ALPHA; + os.xml.appendElement(os.state.v4.LayerTag.FILL_OPACITY, layerEl, value); + } + break; case 'size': if (bfs) { value = value != null ? Math.floor(value) : os.style.DEFAULT_FEATURE_SIZE; diff --git a/src/os/style/style.js b/src/os/style/style.js index cad030ab0..3d1d642f1 100644 --- a/src/os/style/style.js +++ b/src/os/style/style.js @@ -25,6 +25,14 @@ goog.require('os.style.StyleType'); os.style.DEFAULT_ALPHA = 1.0; +/** + * Default alpha for polygon fills. + * @type {number} + * @const + */ +os.style.DEFAULT_FILL_ALPHA = 0.0; + + /** * Default color for tile/feature layers. * @type {string} @@ -41,6 +49,14 @@ os.style.DEFAULT_LAYER_COLOR = 'rgba(255,255,255,1)'; os.style.DEFAULT_INVERSE_COLOR = 'rgba(255,0,0,1)'; +/** + * Default fill color for tile/feature layers. + * @type {string} + * @const + */ +os.style.DEFAULT_FILL_COLOR = 'rgba(255,255,255,0)'; + + /** * Default size for geometries. Radius for points. * @type {number} @@ -359,10 +375,13 @@ os.style.DEFAULT_VECTOR_CONFIG = { 'type': 'circle', 'radius': os.style.DEFAULT_FEATURE_SIZE, 'fill': { - 'color': os.style.DEFAULT_LAYER_COLOR + 'color': os.style.DEFAULT_FILL_COLOR } }, // this will only be applied to line and polygon types + 'fill': { + 'color': os.style.DEFAULT_FILL_COLOR + }, 'stroke': { 'width': os.style.DEFAULT_STROKE_WIDTH, 'color': os.style.DEFAULT_LAYER_COLOR diff --git a/src/os/style/stylefield.js b/src/os/style/stylefield.js index 71294d164..af641dc31 100644 --- a/src/os/style/stylefield.js +++ b/src/os/style/stylefield.js @@ -11,6 +11,8 @@ os.style.StyleField = { CENTER_SHAPE: 'centerShape', COLOR: 'color', FILL: 'fill', + FILL_COLOR: 'fillColor', + FILL_OPACITY: 'fillOpacity', ICON: 'icon', IMAGE: 'image', LABELS: 'labels', diff --git a/src/os/ui/featureedit.js b/src/os/ui/featureedit.js index 76d2a812b..7e0e03721 100644 --- a/src/os/ui/featureedit.js +++ b/src/os/ui/featureedit.js @@ -156,7 +156,7 @@ os.ui.FeatureEditCtrl = function($scope, $element, $timeout) { * The feature color. * @type {string} */ - this['color'] = os.style.DEFAULT_LAYER_COLOR; + this['color'] = os.color.toHexString(os.style.DEFAULT_LAYER_COLOR); /** * The feature opacity. @@ -170,6 +170,18 @@ os.ui.FeatureEditCtrl = function($scope, $element, $timeout) { */ this['size'] = os.style.DEFAULT_FEATURE_SIZE; + /** + * The feature fill color + * @type {string} + */ + this['fillColor'] = os.color.toHexString(os.style.DEFAULT_LAYER_COLOR); + + /** + * The feature fill opacity + * @type {string} + */ + this['fillOpacity'] = os.style.DEFAULT_FILL_ALPHA; + /** * The feature icon. * @type {!osx.icon.Icon} @@ -364,7 +376,7 @@ os.ui.FeatureEditCtrl = function($scope, $element, $timeout) { * Configured label color. * @type {string} */ - this['labelColor'] = os.style.DEFAULT_LAYER_COLOR; + this['labelColor'] = os.color.toHexString(os.style.DEFAULT_LAYER_COLOR); /** * Configured label size. @@ -508,6 +520,10 @@ os.ui.FeatureEditCtrl = function($scope, $element, $timeout) { $scope.$watch('ctrl.labelColor', this.updatePreview.bind(this)); $scope.$watch('ctrl.labelSize', this.updatePreview.bind(this)); $scope.$watch('ctrl.showLabels', this.updatePreview.bind(this)); + $scope.$on('fillColor.change', this.onFillColorChange.bind(this)); + $scope.$on('fillColor.reset', this.onFillColorReset.bind(this)); + $scope.$on('fillOpacity.slidestop', this.onFillOpacityChange.bind(this)); + $scope.$on('fillOpacity.slide', this.onFillOpacityChange.bind(this)); $scope.$on(os.ui.WindowEventType.CANCEL, this.onCancel.bind(this)); $scope.$on(os.ui.icon.IconPickerEventType.CHANGE, this.onIconChange.bind(this)); @@ -1014,6 +1030,12 @@ os.ui.FeatureEditCtrl.prototype.loadFromFeature = function(feature) { this['centerIcon'] = icon; } + if (config['fill'] && config['fill']['color']) { + this['fillColor'] = os.color.toHexString(config['fill']['color']); + var opacity = os.color.toRgbArray(config['fill']['color']); + this['fillOpacity'] = opacity[3]; + } + var lineDash = os.style.getConfigLineDash(config); if (lineDash) { this['lineDash'] = lineDash; @@ -1254,6 +1276,15 @@ os.ui.FeatureEditCtrl.prototype.setFeatureConfig_ = function(config) { os.style.setConfigOpacityColor(config, 0); } + var fillColor = ol.color.asArray(this['fillColor']); + var fillOpacity = os.color.normalizeOpacity(this['fillOpacity']); + fillColor[3] = fillOpacity; + fillColor = os.style.toRgbaString(fillColor); + + if (color != fillColor) { + os.style.setConfigColor(config, fillColor, [os.style.StyleField.FILL]); + } + // set icon config if selected var useCenter = this.showCenterIcon(); if ((this['shape'] === os.style.ShapeType.ICON || useCenter) && config['image'] != null) { @@ -1395,8 +1426,14 @@ os.ui.FeatureEditCtrl.prototype.onColumnChange = function(event) { * @export */ os.ui.FeatureEditCtrl.prototype.onIconColorChange = function(opt_new, opt_old) { - if (opt_new != opt_old && this['labelColor'] == opt_old) { - this['labelColor'] = opt_new; + if (opt_new != opt_old) { + if (this['labelColor'] == opt_old) { + this['labelColor'] = opt_new; + } + + if (this['fillColor'] == opt_old) { + this['fillColor'] = opt_new; + } } this.updatePreview(); @@ -1449,6 +1486,47 @@ os.ui.FeatureEditCtrl.prototype.onLabelColorReset = function(event) { }; +/** + * Handles when the fill opacity is changed + * @param {angular.Scope.Event} event The Angular event. + * @param {osx.icon.Icon} value The new value. + * @export + */ +os.ui.FeatureEditCtrl.prototype.onFillOpacityChange = function(event, value) { + event.stopPropagation(); + + this['fillOpacity'] = value; + this.updatePreview(); +}; + + +/** + * Handles when the fill color is changed + * @param {angular.Scope.Event} event The Angular event. + * @param {string} value + * @export + */ +os.ui.FeatureEditCtrl.prototype.onFillColorChange = function(event, value) { + event.stopPropagation(); + + this['fillColor'] = value; + this.updatePreview(); +}; + + +/** + * Handles fill color reset + * @param {angular.Scope.Event} event + * @export + */ +os.ui.FeatureEditCtrl.prototype.onFillColorReset = function(event) { + event.stopPropagation(); + + this['fillColor'] = this['color']; + this.updatePreview(); +}; + + /** * Get the minimum value for the semi-major ellipse axis by converting semi-minor to the semi-major units. * @@ -1695,6 +1773,10 @@ os.ui.FeatureEditCtrl.updateFeatureStyle = function(feature) { config['stroke']['width'] = config['stroke']['width'] || size; config['stroke']['lineDash'] = lineDash; + // set fill for lines/polygons on the base config + config['fill'] = config['fill'] || {}; + config['fill']['color'] = os.style.toRgbaString(config['fill']['color'] || color); + // drop opacity to 0 if the shape style is set to 'None' if (shape === os.style.ShapeType.NONE) { os.style.setConfigOpacityColor(config, 0); diff --git a/src/os/ui/file/kml/abstractkmlexporter.js b/src/os/ui/file/kml/abstractkmlexporter.js index 5dd8c3544..401f64a80 100644 --- a/src/os/ui/file/kml/abstractkmlexporter.js +++ b/src/os/ui/file/kml/abstractkmlexporter.js @@ -725,10 +725,11 @@ os.ui.file.kml.AbstractKMLExporter.prototype.addGeometryNode = function(item, no * @param {T} item The item * @param {string} styleId The style id * @param {string} color The item color + * @param {string} fillColor The item fill color * @param {os.ui.file.kml.Icon=} opt_icon The item icon * @protected */ -os.ui.file.kml.AbstractKMLExporter.prototype.createStyle = function(item, styleId, color, opt_icon) { +os.ui.file.kml.AbstractKMLExporter.prototype.createStyle = function(item, styleId, color, fillColor, opt_icon) { var styleEl = os.xml.createElementNS('Style', this.kmlNS, this.doc, undefined, { 'id': styleId }); @@ -769,8 +770,8 @@ os.ui.file.kml.AbstractKMLExporter.prototype.createStyle = function(item, styleI os.xml.appendElementNS('width', this.kmlNS, lineStyleEl, 2); var polyStyleEl = os.xml.appendElementNS('PolyStyle', this.kmlNS, styleEl); - os.xml.appendElementNS('color', this.kmlNS, polyStyleEl, color); - os.xml.appendElementNS('fill', this.kmlNS, polyStyleEl, 0); + os.xml.appendElementNS('color', this.kmlNS, polyStyleEl, fillColor); + os.xml.appendElementNS('fill', this.kmlNS, polyStyleEl, 1); var firstFolder = this.kmlDoc.querySelector('Folder'); if (firstFolder) { @@ -807,6 +808,16 @@ os.ui.file.kml.AbstractKMLExporter.prototype.getChildren = function(item) { os.ui.file.kml.AbstractKMLExporter.prototype.getColor = function(item) {}; +/** + * Get the fill color of an item. This should return an ABGR string that can be dropped directly into the KML. + * @abstract + * @param {T} item The item + * @return {string} The item's fill color as an ABGR string + * @protected + */ +os.ui.file.kml.AbstractKMLExporter.prototype.getFillColor = function(item) {}; + + /** * Get the type of KML element represented by the item. * @@ -996,6 +1007,11 @@ os.ui.file.kml.AbstractKMLExporter.prototype.getStyleId = function(item) { styleParts.push(color); } + var fillColor = this.getFillColor(item); + if (this.useItemColor || type == os.ui.file.kml.StyleType.DEFAULT) { + styleParts.push(fillColor); + } + var icon = type == os.ui.file.kml.StyleType.DEFAULT ? undefined : this.getIcon(item); if (type == os.ui.file.kml.StyleType.ICON && this.useItemIcon) { // override the default icon with the item's icon @@ -1013,7 +1029,7 @@ os.ui.file.kml.AbstractKMLExporter.prototype.getStyleId = function(item) { styleId = styleParts.join('-'); if (!(styleId in this.styles_)) { - this.createStyle(item, styleId, color, icon); + this.createStyle(item, styleId, color, fillColor, icon); } return styleId; diff --git a/src/os/ui/layer/vectorlayerui.js b/src/os/ui/layer/vectorlayerui.js index 1ae97415c..9dbcf1a90 100644 --- a/src/os/ui/layer/vectorlayerui.js +++ b/src/os/ui/layer/vectorlayerui.js @@ -4,20 +4,28 @@ goog.provide('os.ui.layer.vectorLayerUIDirective'); goog.require('goog.color'); goog.require('os.MapChange'); goog.require('os.array'); +goog.require('os.command.FeatureOpacity'); +goog.require('os.command.FeatureStrokeOpacity'); +goog.require('os.command.LayerStyle'); goog.require('os.command.VectorLayerAutoRefresh'); goog.require('os.command.VectorLayerCenterShape'); goog.require('os.command.VectorLayerColor'); +goog.require('os.command.VectorLayerFillColor'); +goog.require('os.command.VectorLayerFillOpacity'); goog.require('os.command.VectorLayerIcon'); goog.require('os.command.VectorLayerLabel'); goog.require('os.command.VectorLayerLabelColor'); goog.require('os.command.VectorLayerLabelSize'); goog.require('os.command.VectorLayerLineDash'); +goog.require('os.command.VectorLayerOpacity'); goog.require('os.command.VectorLayerReplaceStyle'); goog.require('os.command.VectorLayerRotation'); goog.require('os.command.VectorLayerShape'); goog.require('os.command.VectorLayerShowLabel'); goog.require('os.command.VectorLayerShowRotation'); goog.require('os.command.VectorLayerSize'); +goog.require('os.command.VectorLayerStrokeColor'); +goog.require('os.command.VectorLayerStrokeOpacity'); goog.require('os.command.VectorUniqueIdCmd'); goog.require('os.data.OSDataManager'); goog.require('os.defines'); @@ -144,6 +152,12 @@ os.ui.layer.VectorLayerUICtrl = function($scope, $element, $timeout) { $scope.$on(os.ui.layer.VectorStyleControlsEventType.CENTER_SHAPE_CHANGE, this.onCenterShapeChange.bind(this)); $scope.$on(os.ui.layer.VectorStyleControlsEventType.LINE_DASH_CHANGE, this.onLineDashChange.bind(this)); + // New default added to the base constructor + this.defaults['fillOpacity'] = os.style.DEFAULT_FILL_ALPHA; + + $scope.$on('fillColor.change', this.onFillColorChange.bind(this)); + $scope.$on('fillColor.reset', this.onFillColorReset.bind(this)); + // label change handlers $scope.$on('labelColor.change', this.onLabelColorChange.bind(this)); $scope.$on('labelColor.reset', this.onLabelColorReset.bind(this)); @@ -165,6 +179,7 @@ os.ui.layer.VectorLayerUICtrl.prototype.initUI = function() { if (this.scope) { this.scope['color'] = this.getColor(); + this.scope['opacity'] = this.getOpacity(); this.scope['size'] = this.getSize(); this.scope['lineDash'] = this.getLineDash(); this.scope['icon'] = this.getIcon(); @@ -174,6 +189,8 @@ os.ui.layer.VectorLayerUICtrl.prototype.initUI = function() { this.scope['centerShape'] = this.getCenterShape(); this.scope['centerShapes'] = this.getCenterShapes(); this.scope['lockable'] = this.getLockable(); + this.scope['fillColor'] = this.getFillColor(); + this.scope['fillOpacity'] = this.getFillOpacity(); this['altitudeMode'] = this.getAltitudeMode(); this['columns'] = this.getColumns(); this['showRotation'] = this.getShowRotation(); @@ -239,6 +256,21 @@ os.ui.layer.VectorLayerUICtrl.prototype.getShapeUIInternal = function() { }; +/** + * @inheritDoc + */ +os.ui.layer.VectorLayerUICtrl.prototype.getProperties = function() { + return { + 'opacity': os.layer.setOpacity, + 'fillOpacity': goog.nullFunction, + 'brightness': os.layer.setBrightness, + 'contrast': os.layer.setContrast, + 'hue': os.layer.setHue, + 'saturation': os.layer.setSaturation + }; +}; + + /** * Decide when to show the rotation option * @@ -256,6 +288,19 @@ os.ui.layer.VectorLayerUICtrl.prototype.showRotationOption = function() { }; +/** + * Decide if we show the fill controls + * @return {boolean} + * @export + */ +os.ui.layer.VectorLayerUICtrl.prototype.showFillStyleControls = function() { + if (this.scope && this.scope['fillOpacity'] !== undefined) { + return true; + } + return false; +}; + + /** * Synchronizes the scope labels. * @@ -290,22 +335,72 @@ os.ui.layer.VectorLayerUICtrl.prototype.reconcileLabelsState_ = function() { os.ui.layer.VectorLayerUICtrl.prototype.onColorChange = function(event, value) { event.stopPropagation(); - var fn = + // Make sure the value includes the current opacity + var colorValue = os.color.toRgbArray(value); + colorValue[3] = this.scope['opacity']; + + // Determine if we are changing both stroke and fill entirely, or keeping opacities separate, or only affecting stroke + var color = this.scope['color']; + var fillColor = this.scope['fillColor']; + var opacity = this.scope['opacity']; + var fillOpacity = this.scope['fillOpacity']; + + this.scope['color'] = os.style.toRgbaString(colorValue); + + if (color == fillColor && opacity == fillOpacity) { + var fn = /** * @param {os.layer.ILayer} layer * @return {os.command.ICommand} */ function(layer) { - return new os.command.VectorLayerColor(layer.getId(), value); + return new os.command.VectorLayerColor(layer.getId(), colorValue); }; - this.createCommand(fn); + this.createCommand(fn); + } else if (color == fillColor) { + // We run these separately so that they retain the different opacities + var fn2 = + /** + * @param {os.layer.ILayer} layer + * @return {os.command.ICommand} + */ + function(layer) { + return new os.command.VectorLayerStrokeColor(layer.getId(), colorValue); + }; + + this.createCommand(fn2); + + // Use the fill's opacity instead of the stroke's opacity + colorValue[3] = fillOpacity; + + var fn3 = + /** + * @param {os.layer.ILayer} layer + * @return {os.command.ICommand} + */ + function(layer) { + return new os.command.VectorLayerFillColor(layer.getId(), colorValue); + }; + + this.createCommand(fn3); + } else { + var fn4 = + /** + * @param {os.layer.ILayer} layer + * @return {os.command.ICommand} + */ + function(layer) { + return new os.command.VectorLayerStrokeColor(layer.getId(), colorValue); + }; + + this.createCommand(fn4); + } }; /** * Handles color reset - * * @param {angular.Scope.Event} event * @protected */ @@ -320,6 +415,124 @@ os.ui.layer.VectorLayerUICtrl.prototype.onColorReset = function(event) { }; +/** + * Handles changes to fill color + * @param {angular.Scope.Event} event + * @param {string} value + * @protected + */ +os.ui.layer.VectorLayerUICtrl.prototype.onFillColorChange = function(event, value) { + event.stopPropagation(); + + // Make sure the value includes the current opacity + var colorValue = os.color.toRgbArray(value); + colorValue[3] = this.scope['fillOpacity']; + + this.scope['fillColor'] = os.style.toRgbaString(colorValue); + + var fn = + /** + * @param {os.layer.ILayer} layer + * @return {os.command.ICommand} + */ + function(layer) { + return new os.command.VectorLayerFillColor(layer.getId(), colorValue); + }; + + this.createCommand(fn); +}; + + +/** + * Handles fill color reset + * @param {angular.Scope.Event} event + * @protected + */ +os.ui.layer.VectorLayerUICtrl.prototype.onFillColorReset = function(event) { + event.stopPropagation(); + + // clear the layer color config value + this.onFillColorChange(event, ''); + + // reset to the layer color + this.scope['fillColor'] = this.getColor(); +}; + + +/** + * @override + */ +os.ui.layer.VectorLayerUICtrl.prototype.onValueChange = function(callback, event, value) { + // If we are not dealing with opacity of fill opacity, let the parent handle this event + if (event.name != 'opacity.slide' && event.name != 'fillOpacity.slide') { + os.ui.layer.VectorLayerUICtrl.base(this, 'onValueChange', callback, event, value); + return; + } + + if (event.name == 'fillOpacity.slide') { + this.scope['fillOpacity'] = value; + } else { + if (this.scope['fillOpacity'] !== undefined && this.scope['opacity'] == this.scope['fillOpacity']) { + var color = os.color.toHexString(this.scope['color']); + var fillColor = os.color.toHexString(this.scope['fillColor']); + if (color == fillColor) { + this.scope['fillOpacity'] = value; + } + } + + this.scope['opacity'] = value; + } +}; + +/** + * @inheritDoc + */ +os.ui.layer.VectorLayerUICtrl.prototype.onSliderStop = function(callback, key, event, value) { + // If we are not dealing with opacity of fill opacity, let the parent handle this event + if (event.name != 'opacity.slidestop' && event.name != 'fillOpacity.slidestop') { + os.ui.layer.VectorLayerUICtrl.base(this, 'onSliderStop', callback, key, event, value); + return; + } + + event.stopPropagation(); + + if (event.name == 'fillOpacity.slidestop') { + var fn = + /** + * @param {os.layer.ILayer} layer + * @return {os.command.ICommand} + */ + function(layer) { + return new os.command.VectorLayerFillOpacity(layer.getId(), value); + }; + + this.createCommand(fn); + } else if (this.scope['fillOpacity'] !== undefined && this.scope['opacity'] == this.scope['fillOpacity']) { + var fn2 = + /** + * @param {os.layer.ILayer} layer + * @return {?os.command.ICommand} + */ + function(layer) { + return new os.command.VectorLayerOpacity(layer.getId(), value); + }; + + this.createCommand(fn2); + } else { + var fn3 = + /** + * @param {os.layer.ILayer} layer + * @return {?os.command.ICommand} + */ + function(layer) { + return new os.command.VectorLayerStrokeOpacity(layer.getId(), value); + }; + + this.createCommand(fn3); + } +}; + + /** * Handles changes to size * @@ -579,6 +792,97 @@ os.ui.layer.VectorLayerUICtrl.prototype.getColor = function() { }; +/** + * Gets the fill color from the item(s) + * @return {?string} a hex color string + * @protected + */ +os.ui.layer.VectorLayerUICtrl.prototype.getFillColor = function() { + var items = /** @type {Array} */ (this.scope['items']); + + if (items) { + for (var i = 0, n = items.length; i < n; i++) { + var layer = items[i].getLayer(); + + if (layer) { + var config = os.style.StyleManager.getInstance().getLayerConfig(items[0].getId()); + + if (config) { + var color = os.style.getConfigColor(config, false, os.style.StyleField.FILL); + color = color || os.style.DEFAULT_LAYER_COLOR; + + if (color) { + return os.color.toHexString(color); + } + } + } + } + } + + return null; +}; + + +/** + * @override + */ +os.ui.layer.VectorLayerUICtrl.prototype.getOpacity = function() { + var items = /** @type {Array} */ (this.scope['items']); + var opacity = os.style.DEFAULT_ALPHA; + + if (items) { + for (var i = 0, n = items.length; i < n; i++) { + var layer = items[i].getLayer(); + + if (layer) { + var config = os.style.StyleManager.getInstance().getLayerConfig(items[0].getId()); + + if (config) { + if (goog.isArray(config)) { + config = config[0]; + } + var color = os.style.getConfigColor(config, true, os.style.StyleField.STROKE); + opacity = color[3]; + } + } + } + } + + return opacity; +}; + + +/** + * Gets the fill opacity from the item(s) + * @return {?number} an opacity amount + * @protected + */ +os.ui.layer.VectorLayerUICtrl.prototype.getFillOpacity = function() { + var items = /** @type {Array} */ (this.scope['items']); + var opacity = os.style.DEFAULT_FILL_ALPHA; + + if (items) { + for (var i = 0, n = items.length; i < n; i++) { + var layer = items[i].getLayer(); + + if (layer) { + var config = os.style.StyleManager.getInstance().getLayerConfig(items[0].getId()); + + if (config) { + if (goog.isArray(config)) { + config = config[0]; + } + var color = os.style.getConfigColor(config, true, os.style.StyleField.FILL); + opacity = color[3]; + } + } + } + } + + return opacity; +}; + + /** * Gets the size from the item(s) * diff --git a/src/os/ui/layer/vectorstylecontrols.js b/src/os/ui/layer/vectorstylecontrols.js index 1df56f536..f09fa9ee4 100644 --- a/src/os/ui/layer/vectorstylecontrols.js +++ b/src/os/ui/layer/vectorstylecontrols.js @@ -30,7 +30,9 @@ os.ui.layer.vectorStyleControlsDirective = function() { replace: true, scope: { 'color': '=', + 'fillColor': '=?', 'opacity': '=', + 'fillOpacity': '=?', 'icon': '=?', 'centerIcon': '=?', 'iconSet': '=?', @@ -172,6 +174,19 @@ os.ui.layer.VectorStyleControlsCtrl.prototype.hasCenter = function() { }; +/** + * Decide if we show the fill controls + * @return {boolean} + * @export + */ +os.ui.layer.VectorStyleControlsCtrl.prototype.showFillStyleControls = function() { + if (this.scope && this.scope['fillOpacity'] !== undefined) { + return true; + } + return false; +}; + + /** * Fire a scope event when the ellipse center shape is changed by the user. * diff --git a/src/plugin/featureaction/featurestyleaction.js b/src/plugin/featureaction/featurestyleaction.js index a76cca4cb..74b03776f 100644 --- a/src/plugin/featureaction/featurestyleaction.js +++ b/src/plugin/featureaction/featurestyleaction.js @@ -21,6 +21,8 @@ plugin.im.action.feature.StyleActionTagName = { COLOR: 'color', ICON_SRC: 'iconSrc', ICON_OPTIONS: 'iconOptions', + FILL_COLOR: 'fillColor', + FILL_OPACITY: 'fillOpacity', LINE_DASH: 'lineDash', OPACITY: 'opacity', ROTATION_COLUMN: 'rotationColumn', @@ -217,6 +219,15 @@ plugin.im.action.feature.StyleAction.prototype.toXml = function() { String(color.length > 3 ? color[3] : 1.0)); } + var fillColor = /** @type {Array} */ + (os.style.getConfigColor(this.styleConfig, true, os.style.StyleField.FILL)); + if (fillColor) { + os.xml.appendElement(plugin.im.action.feature.StyleActionTagName.FILL_COLOR, element, + os.color.toHexString(fillColor)); + os.xml.appendElement(plugin.im.action.feature.StyleActionTagName.FILL_OPACITY, element, + String(fillColor.length > 3 ? fillColor[3] : 0)); + } + var size = os.style.getConfigSize(this.styleConfig); if (size != null) { os.xml.appendElement(plugin.im.action.feature.StyleActionTagName.SIZE, element, String(size)); @@ -284,6 +295,20 @@ plugin.im.action.feature.StyleAction.prototype.fromXml = function(xml) { os.style.setConfigColor(styleConfig, color); } + var fillColor = os.xml.getChildValue(xml, plugin.im.action.feature.StyleActionTagName.FILL_COLOR); + if (os.color.isColorString(fillColor)) { + var fillColorArr = os.color.toRgbArray(fillColor); + if (fillColorArr) { + var fillOpacityVal = parseFloat( + os.xml.getChildValue(xml, plugin.im.action.feature.StyleActionTagName.FILL_OPACITY)); + var fillOpacity = !isNaN(fillOpacityVal) ? goog.math.clamp(fillOpacityVal, 0, 1) : 1.0; + fillColorArr[3] = fillOpacity; + fillColor = os.style.toRgbaString(fillColorArr); + } + + os.style.setConfigColor(styleConfig, fillColor, [os.style.StyleField.FILL]); + } + var size = parseFloat(os.xml.getChildValue(xml, plugin.im.action.feature.StyleActionTagName.SIZE)); if (!isNaN(size)) { os.style.setConfigSize(styleConfig, size); diff --git a/src/plugin/featureaction/ui/featurestyleactionconfig.js b/src/plugin/featureaction/ui/featurestyleactionconfig.js index 9a9eefe9e..9105aa8c0 100644 --- a/src/plugin/featureaction/ui/featurestyleactionconfig.js +++ b/src/plugin/featureaction/ui/featurestyleactionconfig.js @@ -3,6 +3,10 @@ goog.provide('plugin.im.action.feature.ui.styleConfigDirective'); goog.require('goog.color'); goog.require('os.color'); +goog.require('os.command.FeatureColor'); +goog.require('os.command.FeatureFillColor'); +goog.require('os.command.FeatureFillOpacity'); +goog.require('os.command.FeatureOpacity'); goog.require('os.object'); goog.require('os.style'); goog.require('os.ui.Module'); @@ -28,7 +32,7 @@ plugin.im.action.feature.ui.styleConfigDirective = function() { template: '
' + + 'show-color-reset="true" fill-color="fillColor" fill-opacity="fillOpacity">' + '
', controller: plugin.im.action.feature.ui.StyleConfigCtrl, @@ -89,7 +93,10 @@ plugin.im.action.feature.ui.StyleConfigCtrl = function($scope, $element) { $scope.$on('color.change', this.onColorChange.bind(this)); $scope.$on('color.reset', this.onColorReset.bind(this)); + $scope.$on('fillColor.change', this.onFillColorChange.bind(this)); + $scope.$on('fillColor.reset', this.onFillColorReset.bind(this)); $scope.$on('opacity.slidestop', this.onOpacityChange.bind(this)); + $scope.$on('fillOpacity.slidestop', this.onOpacityChange.bind(this)); $scope.$on('size.slidestop', this.onSizeChange.bind(this)); $scope.$on(os.ui.layer.VectorStyleControlsEventType.LINE_DASH_CHANGE, this.onLineDashChange.bind(this)); $scope.$on(os.ui.icon.IconPickerEventType.CHANGE, this.onIconChange.bind(this)); @@ -107,16 +114,53 @@ goog.inherits(plugin.im.action.feature.ui.StyleConfigCtrl, plugin.im.action.feat */ plugin.im.action.feature.ui.StyleConfigCtrl.prototype.initialize = function() { if (this.styleConfig) { - var color = /** @type {Array} */ (os.style.getConfigColor(this.styleConfig, true)); + var color = /** @type {Array} */ + (os.style.getConfigColor(this.styleConfig, true, os.style.StyleField.STROKE)); + + if (!color) { + color = os.style.getConfigColor(this.styleConfig, true); + } + if (color) { - this.scope['color'] = this.initialColor = goog.color.rgbArrayToHex(color); - this.scope['opacity'] = color.length > 3 ? color[3] : 1.0; + this.scope['color'] = this.initialColor = os.color.toHexString(color); + if (color.length < 4) { + color[3] = os.style.DEFAULT_ALPHA; + } + + this.scope['opacity'] = color[3]; } else { this.scope['color'] = os.color.toHexString(os.style.DEFAULT_LAYER_COLOR); - this.scope['opacity'] = 1.0; + this.scope['opacity'] = os.style.DEFAULT_ALPHA; + + color = os.color.toRgbArray(this.scope['color']); + color[3] = this.scope['opacity']; + } + + var fill = /** @type {Array} */ (os.style.getConfigColor(this.styleConfig, true, os.style.StyleField.FILL)); + + if (fill) { + this.scope['fillColor'] = os.color.toHexString(fill); + + if (fill.length < 4) { + fill[3] = os.style.DEFAULT_FILL_ALPHA; + } + + this.scope['fillOpacity'] = fill[3]; + } else { + this.scope['fillColor'] = os.color.toHexString(os.style.DEFAULT_FILL_COLOR); + this.scope['fillOpacity'] = os.style.DEFAULT_FILL_ALPHA; + + fill = os.color.toRgbArray(this.scope['fillColor']); + fill[3] = this.scope['fillOpacity']; } - os.style.setConfigColor(this.styleConfig, os.style.getConfigColor(this.styleConfig)); + // Standardize the stroke color + var strokeColor = os.style.toRgbaString(color); + os.style.setConfigColor(this.styleConfig, strokeColor); + + // If we have a fill color, standardize that too + var fillColor = os.style.toRgbaString(fill); + os.style.setConfigColor(this.styleConfig, fillColor, [os.style.StyleField.FILL]); this.scope['size'] = os.style.getConfigSize(this.styleConfig); this.scope['lineDash'] = os.style.getConfigLineDash(this.styleConfig); @@ -187,9 +231,68 @@ plugin.im.action.feature.ui.StyleConfigCtrl.prototype.onColorChange = function(e color = os.style.toRgbaString(colorArr); } - os.style.setConfigColor(this.styleConfig, color); + // update the fill color with the correct opacity + var fillColor = value ? os.style.toRgbaString(value) : os.style.DEFAULT_FILL_COLOR; + var fillOpacity = /** @type {number|undefined} */ (this.scope['fillOpacity']); + var fillColorArr = os.color.toRgbArray(fillColor); + if (fillColorArr && fillOpacity != null) { + fillColorArr[3] = fillOpacity; + fillColor = os.style.toRgbaString(fillColorArr); + } + + // Determine if we are changing both stroke and fill entirely, or keeping opacities separate, or only affecting stroke + var strokeColorHex = os.color.toHexString(this.scope['color']); + var fillColorHex = os.color.toHexString(this.scope['fillColor']); + var strokeColorOpacity = this.scope['opacity']; + var fillColorOpacity = this.scope['fillOpacity']; + + if (strokeColorHex == fillColorHex && strokeColorOpacity == fillColorOpacity) { + // change both to be the same + os.style.setConfigColor(this.styleConfig, color); + this.scope['color'] = os.color.toHexString(color); + this.scope['fillColor'] = os.color.toHexString(color); + } else if (strokeColorHex == fillColorHex) { + // change the color, but not the opacity, of each one separately + os.style.setConfigColor(this.styleConfig, color); + this.scope['color'] = os.color.toHexString(color); + + os.style.setConfigColor(this.styleConfig, fillColor, [os.style.StyleField.FILL]); + this.scope['fillColor'] = os.color.toHexString(fillColor); + } else { + // change just the stroke color + os.style.setConfigColor(this.styleConfig, color); + this.scope['color'] = os.color.toHexString(color); + } + } +}; + + +/** + * Handle fill color change. + * + * @param {?angular.Scope.Event} event The Angular event. + * @param {string|undefined} value The new color value. + * @protected + */ +plugin.im.action.feature.ui.StyleConfigCtrl.prototype.onFillColorChange = function(event, value) { + if (event) { + event.stopPropagation(); + } + + if (this.styleConfig) { + var color = value ? os.style.toRgbaString(value) : os.style.DEFAULT_FILL_COLOR; + + // update the color with the correct opacity + var colorArr = os.color.toRgbArray(color); + var opacity = /** @type {number|undefined} */ (this.scope['fillOpacity']); + if (colorArr && opacity != null) { + colorArr[3] = opacity; + color = os.style.toRgbaString(colorArr); + } + + os.style.setConfigColor(this.styleConfig, color, [os.style.StyleField.FILL]); - this.scope['color'] = os.color.toHexString(color); + this.scope['fillColor'] = os.color.toHexString(color); } }; @@ -210,6 +313,22 @@ plugin.im.action.feature.ui.StyleConfigCtrl.prototype.onColorReset = function(ev }; +/** + * Handle fill color reset. + * + * @param {?angular.Scope.Event} event The Angular event. + * @protected + */ +plugin.im.action.feature.ui.StyleConfigCtrl.prototype.onFillColorReset = function(event) { + if (event) { + event.stopPropagation(); + } + + // reset the color to the initial value + this.onFillColorChange(event, os.style.DEFAULT_FILL_COLOR); +}; + + /** * Handle icon change. * @@ -240,8 +359,34 @@ plugin.im.action.feature.ui.StyleConfigCtrl.prototype.onOpacityChange = function event.stopPropagation(); } - if (this.styleConfig && value != null) { - os.style.setConfigOpacityColor(this.styleConfig, value); + var color; + + if (event.name == 'fillOpacity.slidestop') { + color = os.style.getConfigColor(this.styleConfig, true, os.style.StyleField.FILL); + color[3] = value; + os.style.setConfigColor(this.styleConfig, color, [os.style.StyleField.FILL]); + + this.scope['fillOpacity'] = value; + } else { + var strokeColorHex = os.color.toHexString(this.scope['color']); + var fillColorHex = os.color.toHexString(this.scope['fillColor']); + var strokeColorOpacity = this.scope['opacity']; + var fillColorOpacity = this.scope['fillOpacity']; + + if (strokeColorHex == fillColorHex && strokeColorOpacity == fillColorOpacity) { + color = os.style.getConfigColor(this.styleConfig, true); + color[3] = value; + os.style.setConfigColor(this.styleConfig, color); + + this.scope['opacity'] = value; + this.scope['fillOpacity'] = value; + } else { + color = os.style.getConfigColor(this.styleConfig, true, os.style.StyleField.STROKE); + color[3] = value; + os.style.setConfigColor(this.styleConfig, color, [os.style.StyleField.STROKE, os.style.StyleField.IMAGE]); + + this.scope['opacity'] = value; + } } }; diff --git a/src/plugin/file/kml/kmlexporter.js b/src/plugin/file/kml/kmlexporter.js index 2370485ec..79907e2aa 100644 --- a/src/plugin/file/kml/kmlexporter.js +++ b/src/plugin/file/kml/kmlexporter.js @@ -91,6 +91,20 @@ plugin.file.kml.KMLExporter.prototype.getColor = function(item) { }; +/** + * @inheritDoc + */ +plugin.file.kml.KMLExporter.prototype.getFillColor = function(item) { + var itemColor = os.feature.getFillColor(item, this.getSource_(item)); + + if (!itemColor || (typeof itemColor != 'string' && !goog.isArray(itemColor))) { + itemColor = os.style.DEFAULT_LAYER_COLOR; + } + + return os.style.toAbgrString(itemColor); +}; + + /** * @inheritDoc */ diff --git a/src/plugin/file/kml/kmlfield.js b/src/plugin/file/kml/kmlfield.js index c4f824183..ba6539667 100644 --- a/src/plugin/file/kml/kmlfield.js +++ b/src/plugin/file/kml/kmlfield.js @@ -58,6 +58,8 @@ plugin.file.kml.SOURCE_FIELDS = [ os.style.StyleField.LABELS, os.style.StyleField.LABEL_COLOR, os.style.StyleField.LABEL_SIZE, + os.style.StyleField.FILL_COLOR, + os.style.StyleField.FILL_OPACITY, os.style.StyleField.SHOW_LABELS ]; diff --git a/src/plugin/file/kml/kmlnodelayerui.js b/src/plugin/file/kml/kmlnodelayerui.js index c8a04202d..096781f8d 100644 --- a/src/plugin/file/kml/kmlnodelayerui.js +++ b/src/plugin/file/kml/kmlnodelayerui.js @@ -3,6 +3,8 @@ goog.provide('plugin.file.kml.KMLNodeLayerUICtrl.UIEventType'); goog.provide('plugin.file.kml.kmlNodeLayerUIDirective'); goog.require('os.command.FeatureCenterShape'); goog.require('os.command.FeatureColor'); +goog.require('os.command.FeatureFillColor'); +goog.require('os.command.FeatureFillOpacity'); goog.require('os.command.FeatureIcon'); goog.require('os.command.FeatureLabel'); goog.require('os.command.FeatureLabelColor'); @@ -12,6 +14,8 @@ goog.require('os.command.FeatureOpacity'); goog.require('os.command.FeatureShape'); goog.require('os.command.FeatureShowLabel'); goog.require('os.command.FeatureSize'); +goog.require('os.command.FeatureStrokeColor'); +goog.require('os.command.FeatureStrokeOpacity'); goog.require('os.command.ParallelCommand'); goog.require('os.data.ColumnDefinition'); goog.require('os.ui.Module'); @@ -97,8 +101,9 @@ plugin.file.kml.KMLNodeLayerUICtrl = function($scope, $element, $timeout) { this['labelColumns'] = defaultColumns; $scope.$on('opacity.slide', this.onOpacityValueChange.bind(this)); - $scope.$on('opacity.slidestart', this.onSliderStart.bind(this)); $scope.$on('opacity.slidestop', this.onOpacityChange.bind(this)); + $scope.$on('fillOpacity.slide', this.onFillOpacityValueChange.bind(this)); + $scope.$on('fillOpacity.slidestop', this.onFillOpacityChange.bind(this)); os.dispatcher.listen(plugin.file.kml.KMLNodeLayerUICtrl.UIEventType.REFRESH, this.initUI, false, this); }; @@ -131,6 +136,19 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.getProperties = function() { }; +/** + * @inheritDoc + */ +plugin.file.kml.KMLNodeLayerUICtrl.prototype.initUI = function() { + plugin.file.kml.KMLNodeLayerUICtrl.base(this, 'initUI'); + + if (this.scope) { + this.scope['fillColor'] = this.getFillColor(); + this.scope['fillOpacity'] = this.getFillOpacity(); + } +}; + + /** * @inheritDoc */ @@ -161,6 +179,66 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.getColor = function() { }; +/** + * @inheritDoc + */ +plugin.file.kml.KMLNodeLayerUICtrl.prototype.getFillColor = function() { + var items = /** @type {Array} */ (this.scope['items']); + + if (items) { + for (var i = 0, n = items.length; i < n; i++) { + var feature = items[i].getFeature(); + if (feature) { + var config = /** @type {Object|undefined} */ (feature.get(os.style.StyleType.FEATURE)); + + if (config) { + if (goog.isArray(config)) { + config = config[0]; + } + + var color = os.style.getConfigColor(config, false, os.style.StyleField.FILL); + color = color || os.style.DEFAULT_LAYER_COLOR; + + if (color) { + return os.color.toHexString(color); + } + } + } + } + } + + return null; +}; + + +/** + * @inheritDoc + */ +plugin.file.kml.KMLNodeLayerUICtrl.prototype.getFillOpacity = function() { + var items = /** @type {Array} */ (this.scope['items']); + var opacity = os.style.DEFAULT_ALPHA; + + if (items) { + for (var i = 0, n = items.length; i < n; i++) { + var feature = items[i].getFeature(); + if (feature) { + var config = /** @type {Object|undefined} */ (feature.get(os.style.StyleType.FEATURE)); + + if (config) { + if (goog.isArray(config)) { + config = config[0]; + } + var color = os.style.getConfigColor(config, true, os.style.StyleField.FILL); + opacity = color[3]; + } + } + } + } + + return opacity; +}; + + /** * @inheritDoc */ @@ -339,7 +417,9 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.getOpacity = function() { if (goog.isArray(config)) { config = config[0]; } - opacity = os.style.getConfigOpacityColor(config) || os.style.DEFAULT_ALPHA; + + var color = os.style.getConfigColor(config, true, os.style.StyleField.STROKE); + opacity = color[3]; } } } @@ -454,10 +534,30 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.getLockable = function() { */ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onOpacityValueChange = function(event, value) { event.stopPropagation(); + + // If we have a fill opacity and it is already the same as the stroke opacity, keep them the same + if (this.scope['fillOpacity'] !== undefined && this.scope['opacity'] == this.scope['fillOpacity']) { + this.scope['fillOpacity'] = value; + } + this.scope['opacity'] = value; // do not set this on the config - the command takes care of that }; +/** + * Handle changes to fill opacity while it changes via slide controls + * + * @param {?angular.Scope.Event} event + * @param {?} value + * @protected + */ +plugin.file.kml.KMLNodeLayerUICtrl.prototype.onFillOpacityValueChange = function(event, value) { + event.stopPropagation(); + + this.scope['fillOpacity'] = value; +}; + + /** * @inheritDoc */ @@ -480,16 +580,101 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onLockChange = function() { plugin.file.kml.KMLNodeLayerUICtrl.prototype.onColorChange = function(event, value) { event.stopPropagation(); - var fn = + // Make sure the value includes the current opacity + var colorValue = os.color.toRgbArray(value); + colorValue[3] = this.scope['opacity']; + + // Determine if we are changing both stroke and fill entirely, or keeping opacities separate, or only affecting stroke + var strokeColorArr = os.color.toRgbArray(this.scope['color']); + strokeColorArr[3] = this.scope['opacity']; + var strokeColorValue = os.style.toRgbaString(strokeColorArr); + var fillColorArr = os.color.toRgbArray(this.scope['fillColor']); + fillColorArr[3] = this.scope['fillOpacity']; + var fillColorValue = os.style.toRgbaString(fillColorArr); + var color = os.color.toHexString(this.scope['color']); + var fillColor = os.color.toHexString(this.scope['fillColor']); + + this.scope['color'] = os.color.toHexString(colorValue); + + if (strokeColorValue == fillColorValue) { + var fn = + /** + * @param {string} layerId + * @param {string} featureId + * @return {os.command.ICommand} + */ + function(layerId, featureId) { + return new os.command.FeatureColor(layerId, featureId, colorValue); + }; + + this.createFeatureCommand(fn); + } else if (color == fillColor) { + // We run these separately so that they retain the different opacities + var fn2 = /** * @param {string} layerId * @param {string} featureId * @return {os.command.ICommand} */ function(layerId, featureId) { - return new os.command.FeatureColor(layerId, featureId, value); + return new os.command.FeatureStrokeColor(layerId, featureId, colorValue); }; + this.createFeatureCommand(fn2); + + // Use the fill's opacity instead of the stroke's opacity + colorValue[3] = this.scope['fillOpacity']; + this.scope['fillColor'] = os.style.toRgbaString(colorValue); + + var fn3 = + /** + * @param {string} layerId + * @param {string} featureId + * @return {os.command.ICommand} + */ + function(layerId, featureId) { + return new os.command.FeatureFillColor(layerId, featureId, colorValue); + }; + + this.createFeatureCommand(fn3); + } else { + var fn4 = + /** + * @param {string} layerId + * @param {string} featureId + * @return {os.command.ICommand} + */ + function(layerId, featureId) { + return new os.command.FeatureStrokeColor(layerId, featureId, colorValue); + }; + + this.createFeatureCommand(fn4); + } +}; + + +/** + * @inheritDoc + */ +plugin.file.kml.KMLNodeLayerUICtrl.prototype.onFillColorChange = function(event, value) { + event.stopPropagation(); + + // Make sure the value includes the current opacity + var colorValue = os.color.toRgbArray(value); + colorValue[3] = this.scope['fillOpacity']; + + this.scope['fillColor'] = os.style.toRgbaString(colorValue); + + var fn = + /** + * @param {string} layerId + * @param {string} featureId + * @return {os.command.ICommand} + */ + function(layerId, featureId) { + return new os.command.FeatureFillColor(layerId, featureId, colorValue); + }; + this.createFeatureCommand(fn); }; @@ -599,9 +784,9 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onCenterShapeChange = function(even /** - * Handles changes to color + * Handle changes to opacity while it changes via slide controls * - * @param {angular.Scope.Event} event + * @param {?angular.Scope.Event} event * @param {number} value * @protected */ @@ -609,7 +794,8 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onOpacityChange = function(event, v event.stopPropagation(); if (value) { - var fn = + if (this.scope['fillOpacity'] !== undefined && this.scope['opacity'] == this.scope['fillOpacity']) { + var fn = /** * @param {string} layerId * @param {string} featureId @@ -619,11 +805,48 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onOpacityChange = function(event, v return new os.command.FeatureOpacity(layerId, featureId, value); }; - this.createFeatureCommand(fn); + this.createFeatureCommand(fn); + } else { + var fn2 = + /** + * @param {string} layerId + * @param {string} featureId + * @return {os.command.ICommand} + */ + function(layerId, featureId) { + return new os.command.FeatureStrokeOpacity(layerId, featureId, value); + }; + + this.createFeatureCommand(fn2); + } } }; +/** + * Handle changes to fill opacity while it changes via slide controls + * + * @param {?angular.Scope.Event} event + * @param {number} value + * @protected + */ +plugin.file.kml.KMLNodeLayerUICtrl.prototype.onFillOpacityChange = function(event, value) { + event.stopPropagation(); + + var fn = + /** + * @param {string} layerId + * @param {string} featureId + * @return {os.command.ICommand} + */ + function(layerId, featureId) { + return new os.command.FeatureFillOpacity(layerId, featureId, value); + }; + + this.createFeatureCommand(fn); +}; + + /** * @inheritDoc */ diff --git a/src/plugin/file/kml/kmltreeexporter.js b/src/plugin/file/kml/kmltreeexporter.js index f81e7c9df..4fcba9e47 100644 --- a/src/plugin/file/kml/kmltreeexporter.js +++ b/src/plugin/file/kml/kmltreeexporter.js @@ -94,6 +94,19 @@ plugin.file.kml.KMLTreeExporter.prototype.getColor = function(item) { }; +/** + * @inheritDoc + */ +plugin.file.kml.KMLTreeExporter.prototype.getFillColor = function(item) { + var featureColor = os.feature.getFillColor(item.getFeature()); + if (!featureColor || (typeof featureColor != 'string' && !goog.isArray(featureColor))) { + featureColor = os.style.DEFAULT_LAYER_COLOR; + } + + return os.style.toAbgrString(featureColor); +}; + + /** * @inheritDoc */ diff --git a/src/plugin/file/kml/ui/kmlnode.js b/src/plugin/file/kml/ui/kmlnode.js index 5a875f169..7bca9f872 100644 --- a/src/plugin/file/kml/ui/kmlnode.js +++ b/src/plugin/file/kml/ui/kmlnode.js @@ -307,6 +307,14 @@ plugin.file.kml.ui.KMLNode.prototype.onFeatureChange = function(event) { this.dispatchEvent(new os.events.PropertyChangeEvent('icons')); this.dispatchEvent(new os.events.PropertyChangeEvent(os.annotation.EventType.CHANGE)); break; + case 'colors': + var source = /** @type {plugin.file.kml.KMLSource} */ (os.feature.getSource(this.feature_)); + var rootNode = source.getRootNode(); + var children = rootNode.getChildren(); + for (var i = 0; i < children.length; i++) { // update icon color + children[i].dispatchEvent(new os.events.PropertyChangeEvent('icons')); + } + break; default: break; } diff --git a/src/plugin/places/places.js b/src/plugin/places/places.js index 3ec1769a1..243ce2a92 100644 --- a/src/plugin/places/places.js +++ b/src/plugin/places/places.js @@ -67,6 +67,8 @@ plugin.places.ExportFields = [ os.style.StyleField.SHOW_LABEL_COLUMNS, os.style.StyleField.LABEL_COLOR, os.style.StyleField.LABEL_SIZE, + os.style.StyleField.FILL_COLOR, + os.style.StyleField.FILL_OPACITY, os.Fields.ALT, os.Fields.ALT_UNITS, os.data.RecordField.ALTITUDE_MODE, diff --git a/views/layer/vector.html b/views/layer/vector.html index 7989cbc3d..f141db940 100644 --- a/views/layer/vector.html +++ b/views/layer/vector.html @@ -8,7 +8,9 @@
- - Opacity - - - - Size - - - - Style - -
-
- -
-
- -
-
- - -
+
+
+ + +
+ +
+
+ +
+ + +
+
- - - - Border - - - - - - Center - - + +
+ +
+ + + +
+
+ +
+ +
+ +
+
+ +
+ + +
+ - - - +
+
+ +
+ + +
+ +
+ +
+ +
+
+
diff --git a/views/plugin/kml/kmlnodelayerui.html b/views/plugin/kml/kmlnodelayerui.html index 59aa3f236..5cf1ea307 100644 --- a/views/plugin/kml/kmlnodelayerui.html +++ b/views/plugin/kml/kmlnodelayerui.html @@ -9,6 +9,8 @@ Date: Fri, 26 Jul 2019 10:31:14 -0600 Subject: [PATCH 02/28] fix(fillstyle): fix how events are dispatched --- src/plugin/file/kml/ui/kmlnode.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/plugin/file/kml/ui/kmlnode.js b/src/plugin/file/kml/ui/kmlnode.js index 7bca9f872..bc0ea1dec 100644 --- a/src/plugin/file/kml/ui/kmlnode.js +++ b/src/plugin/file/kml/ui/kmlnode.js @@ -308,12 +308,8 @@ plugin.file.kml.ui.KMLNode.prototype.onFeatureChange = function(event) { this.dispatchEvent(new os.events.PropertyChangeEvent(os.annotation.EventType.CHANGE)); break; case 'colors': - var source = /** @type {plugin.file.kml.KMLSource} */ (os.feature.getSource(this.feature_)); - var rootNode = source.getRootNode(); - var children = rootNode.getChildren(); - for (var i = 0; i < children.length; i++) { // update icon color - children[i].dispatchEvent(new os.events.PropertyChangeEvent('icons')); - } + this.dispatchEvent(new os.events.PropertyChangeEvent('icons')); + this.dispatchEvent(new os.events.PropertyChangeEvent(os.annotation.EventType.CHANGE)); break; default: break; From 9108dbdd5b08605fd3b5a4cd1dec434a6be15832 Mon Sep 17 00:00:00 2001 From: Kevin Wilson Date: Fri, 26 Jul 2019 13:25:05 -0600 Subject: [PATCH 03/28] fix(fillstyle): fixes from code review Fix an issue when undoing fill opacity. Fix when sliding stroke opacity when using Feature Edit dialog. --- .../command/feature/featurefillopacitycmd.js | 9 ++++++-- src/os/ui/featureedit.js | 22 +++++++++++++++++-- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/os/command/feature/featurefillopacitycmd.js b/src/os/command/feature/featurefillopacitycmd.js index 77808fcb4..56cb75fd6 100644 --- a/src/os/command/feature/featurefillopacitycmd.js +++ b/src/os/command/feature/featurefillopacitycmd.js @@ -30,7 +30,7 @@ goog.inherits(os.command.FeatureFillOpacity, os.command.AbstractFeatureStyle); * @type {number} * @const */ -os.command.FeatureFillOpacity.DEFAULT_OPACITY = 1; +os.command.FeatureFillOpacity.DEFAULT_OPACITY = os.style.DEFAULT_FILL_ALPHA; /** @@ -43,7 +43,12 @@ os.command.FeatureFillOpacity.prototype.getOldValue = function() { config = config[0]; } - return config ? os.style.getConfigOpacityColor(config) : os.command.FeatureFillOpacity.DEFAULT_OPACITY; + if (config) { + var color = os.style.getConfigColor(config, true, os.style.StyleField.FILL); + return color[3]; + } else { + return os.command.FeatureFillOpacity.DEFAULT_OPACITY; + } }; diff --git a/src/os/ui/featureedit.js b/src/os/ui/featureedit.js index 7e0e03721..565718fa4 100644 --- a/src/os/ui/featureedit.js +++ b/src/os/ui/featureedit.js @@ -520,10 +520,10 @@ os.ui.FeatureEditCtrl = function($scope, $element, $timeout) { $scope.$watch('ctrl.labelColor', this.updatePreview.bind(this)); $scope.$watch('ctrl.labelSize', this.updatePreview.bind(this)); $scope.$watch('ctrl.showLabels', this.updatePreview.bind(this)); + $scope.$on('opacity.slide', this.onOpacityValueChange.bind(this)); $scope.$on('fillColor.change', this.onFillColorChange.bind(this)); $scope.$on('fillColor.reset', this.onFillColorReset.bind(this)); $scope.$on('fillOpacity.slidestop', this.onFillOpacityChange.bind(this)); - $scope.$on('fillOpacity.slide', this.onFillOpacityChange.bind(this)); $scope.$on(os.ui.WindowEventType.CANCEL, this.onCancel.bind(this)); $scope.$on(os.ui.icon.IconPickerEventType.CHANGE, this.onIconChange.bind(this)); @@ -1486,10 +1486,28 @@ os.ui.FeatureEditCtrl.prototype.onLabelColorReset = function(event) { }; +/** + * Handles when the opacity slider has moved + * @param {angular.Scope.Event} event The Angular event. + * @param {number} value The new value. + * @export + */ +os.ui.FeatureEditCtrl.prototype.onOpacityValueChange = function(event, value) { + event.stopPropagation(); + + // If we have a fill opacity and it is already the same as the stroke opacity, keep them the same + if (this['fillOpacity'] !== undefined && this['opacity'] == this['fillOpacity']) { + this['fillOpacity'] = value; + } + + this['opacity'] = value; +} + + /** * Handles when the fill opacity is changed * @param {angular.Scope.Event} event The Angular event. - * @param {osx.icon.Icon} value The new value. + * @param {number} value The new value. * @export */ os.ui.FeatureEditCtrl.prototype.onFillOpacityChange = function(event, value) { From fb122c6bd30c2602374d5a6fc25eae11640c6db9 Mon Sep 17 00:00:00 2001 From: Kevin Wilson Date: Fri, 26 Jul 2019 13:39:13 -0600 Subject: [PATCH 04/28] fix(fillstyle): lint fix --- src/os/ui/featureedit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/os/ui/featureedit.js b/src/os/ui/featureedit.js index 565718fa4..6911cf307 100644 --- a/src/os/ui/featureedit.js +++ b/src/os/ui/featureedit.js @@ -1501,7 +1501,7 @@ os.ui.FeatureEditCtrl.prototype.onOpacityValueChange = function(event, value) { } this['opacity'] = value; -} +}; /** From 5700858f21e32fd115ea43a53cc9d590451e8beb Mon Sep 17 00:00:00 2001 From: Kevin Wilson Date: Tue, 6 Aug 2019 08:04:30 -0600 Subject: [PATCH 05/28] fix(fillstyle): consolidate multiple command files into fewer files --- src/os/command/feature/featurecolorcmd.js | 92 +++++++++++-- src/os/command/feature/featurefillcolorcmd.js | 119 ----------------- .../command/feature/featurefillopacitycmd.js | 80 ------------ src/os/command/feature/featureopacitycmd.js | 95 +++++++++++++- .../command/feature/featurestrokecolorcmd.js | 123 ------------------ .../feature/featurestrokeopacitycmd.js | 75 ----------- src/os/command/vectorlayercolorcmd.js | 102 ++++++++++++--- src/os/command/vectorlayerfillcolorcmd.js | 90 ------------- src/os/command/vectorlayerfillopacitycmd.js | 69 ---------- src/os/command/vectorlayeropacitycmd.js | 90 ++++++++++--- src/os/command/vectorlayerstrokecolorcmd.js | 88 ------------- src/os/command/vectorlayerstrokeopacitycmd.js | 69 ---------- src/os/ui/layer/vectorlayerui.js | 39 +++--- .../ui/featurestyleactionconfig.js | 4 - src/plugin/file/kml/kmlnodelayerui.js | 17 +-- 15 files changed, 358 insertions(+), 794 deletions(-) delete mode 100644 src/os/command/feature/featurefillcolorcmd.js delete mode 100644 src/os/command/feature/featurefillopacitycmd.js delete mode 100644 src/os/command/feature/featurestrokecolorcmd.js delete mode 100644 src/os/command/feature/featurestrokeopacitycmd.js delete mode 100644 src/os/command/vectorlayerfillcolorcmd.js delete mode 100644 src/os/command/vectorlayerfillopacitycmd.js delete mode 100644 src/os/command/vectorlayerstrokecolorcmd.js delete mode 100644 src/os/command/vectorlayerstrokeopacitycmd.js diff --git a/src/os/command/feature/featurecolorcmd.js b/src/os/command/feature/featurecolorcmd.js index e00ddbce4..cd9315c73 100644 --- a/src/os/command/feature/featurecolorcmd.js +++ b/src/os/command/feature/featurecolorcmd.js @@ -13,13 +13,33 @@ goog.require('os.metrics'); * @param {string} layerId * @param {string} featureId * @param {Array|string} color - * @param {(Array|string)=} opt_oldColor + * @param {(Array|string|null)=} opt_oldColor + * @param {string=} opt_changeMode * @constructor */ -os.command.FeatureColor = function(layerId, featureId, color, opt_oldColor) { +os.command.FeatureColor = function(layerId, featureId, color, opt_oldColor, opt_changeMode) { os.command.FeatureColor.base(this, 'constructor', layerId, featureId, color, opt_oldColor); - this.title = 'Change Feature Color'; - this.metricKey = os.metrics.Layer.FEATURE_COLOR; + + this.changeMode = opt_changeMode; + + switch (this.changeMode) { + case os.command.FeatureColor.MODE.FILL: + this.title = 'Change Feature Fill Color'; + this.metricKey = os.metrics.Layer.FEATURE_FILL_COLOR; + this.defaultColor = os.command.FeatureColor.DEFAULT_FILL_COLOR; + break; + case os.command.FeatureColor.MODE.STROKE: + this.title = 'Change Feature Stroke Color'; + this.metricKey = os.metrics.Layer.FEATURE_STROKE_COLOR; + this.defaultColor = os.command.FeatureColor.DEFAULT_COLOR; + break; + default: + case os.command.FeatureColor.MODE.COMBINED: + this.title = 'Change Feature Color'; + this.metricKey = os.metrics.Layer.FEATURE_COLOR; + this.defaultColor = os.command.FeatureColor.DEFAULT_COLOR; + break; + } if (!color) { var feature = /** @type {ol.Feature} */ (this.getFeature()); @@ -49,6 +69,20 @@ goog.inherits(os.command.FeatureColor, os.command.AbstractFeatureStyle); os.command.FeatureColor.DEFAULT_COLOR = 'rgba(255,255,255,1)'; +/** + * @type {string} + * @const + */ +os.command.FeatureColor.DEFAULT_FILL_COLOR = 'rgba(255,255,255,0)'; + + +os.command.FeatureColor.MODE = { + COMBINED: 'combined', + FILL: 'fill', + STROKE: 'stroke' +}; + + /** * @inheritDoc */ @@ -59,7 +93,24 @@ os.command.FeatureColor.prototype.getOldValue = function() { config = config[0]; } - return config ? os.style.getConfigColor(config) : os.command.FeatureColor.DEFAULT_COLOR; + var ret = this.defaultColor; + + if (config) { + switch (this.changeMode) { + case os.command.FeatureColor.MODE.FILL: + ret = os.style.getConfigColor(config, false, os.style.StyleField.FILL); + break; + case os.command.FeatureColor.MODE.STROKE: + ret = os.style.getConfigColor(config, false, os.style.StyleField.STROKE); + break; + default: + case os.command.FeatureColor.MODE.COMBINED: + ret = os.style.getConfigColor(config); + break; + } + } + + return ret; }; @@ -80,13 +131,34 @@ os.command.FeatureColor.prototype.getLabelValue = function() { */ os.command.FeatureColor.prototype.applyValue = function(configs, value) { var color = os.style.toRgbaString(/** @type {string} */ (value)); - for (var i = 0; i < configs.length; i++) { - os.style.setConfigColor(configs[i], color); - } - if (this.oldValue == this.getLabelValue()) { - this.applyLabelValue(configs, value); + switch (this.changeMode) { + case os.command.FeatureColor.MODE.FILL: + for (var i = 0; i < configs.length; i++) { + os.style.setConfigColor(configs[i], color, [os.style.StyleField.FILL]); + } + break; + case os.command.FeatureColor.MODE.STROKE: + for (var i = 0; i < configs.length; i++) { + os.style.setConfigColor(configs[i], color, [os.style.StyleField.STROKE, os.style.StyleField.IMAGE]); + } + + if (this.oldValue == this.getLabelValue()) { + this.applyLabelValue(configs, value); + } + break; + default: + case os.command.FeatureColor.MODE.COMBINED: + for (var i = 0; i < configs.length; i++) { + os.style.setConfigColor(configs[i], color); + } + + if (this.oldValue == this.getLabelValue()) { + this.applyLabelValue(configs, value); + } + break; } + os.command.FeatureColor.base(this, 'applyValue', configs, value); }; diff --git a/src/os/command/feature/featurefillcolorcmd.js b/src/os/command/feature/featurefillcolorcmd.js deleted file mode 100644 index 02e9b2a41..000000000 --- a/src/os/command/feature/featurefillcolorcmd.js +++ /dev/null @@ -1,119 +0,0 @@ -goog.provide('os.command.FeatureFillColor'); - -goog.require('os.command.AbstractFeatureStyle'); -goog.require('os.events.PropertyChangeEvent'); -goog.require('os.metrics'); - - - -/** - * Changes the fill color of a feature - * @extends {os.command.AbstractFeatureStyle} - * @param {string} layerId - * @param {string} featureId - * @param {Array|string} color - * @param {(Array|string)=} opt_oldColor - * @constructor - */ -os.command.FeatureFillColor = function(layerId, featureId, color, opt_oldColor) { - os.command.FeatureFillColor.base(this, 'constructor', layerId, featureId, color, opt_oldColor); - this.title = 'Change Feature Fill Color'; - this.metricKey = os.metrics.Layer.FEATURE_FILL_COLOR; - - if (!color) { - var feature = this.getFeature(); - var config = /** @type {Object|undefined} */ (feature.get(os.style.StyleType.FEATURE)); - - if (config) { - if (goog.isArray(config)) { - config = config[0]; - } - var configColor = /** @type {Array|string|undefined} */ (os.style.getConfigColor(config)); - - if (configColor) { - color = os.color.toHexString(color); - } - } - } - - // Make sure the value is a string - this.value = os.style.toRgbaString(color); -}; -goog.inherits(os.command.FeatureFillColor, os.command.AbstractFeatureStyle); - - -/** - * @type {string} - * @const - */ -os.command.FeatureFillColor.DEFAULT_COLOR = 'rgba(255,255,255,0)'; - - -/** - * @inheritDoc - */ -os.command.FeatureFillColor.prototype.getOldValue = function() { - var feature = /** @type {ol.Feature} */ (this.getFeature()); - var config = /** @type {Array|Object|undefined} */ (this.getFeatureConfigs(feature)); - if (goog.isArray(config)) { - config = config[0]; - } - - if (config) { - return os.style.getConfigColor(config, false, os.style.StyleField.FILL); - } else { - return os.command.FeatureFillColor.DEFAULT_COLOR; - } -}; - - -/** - * Gets the old label color - * @return {Array|string|undefined} - */ -os.command.FeatureFillColor.prototype.getLabelValue = function() { - var feature = /** @type {ol.Feature} */ (this.getFeature()); - var labelColor = /** @type {Array|string|undefined} */ (feature.get(os.style.StyleField.LABEL_COLOR)); - return labelColor ? labelColor : os.style.DEFAULT_LAYER_COLOR; -}; - - -/** - * @inheritDoc - */ -os.command.FeatureFillColor.prototype.applyValue = function(configs, value) { - var color = os.style.toRgbaString(/** @type {string} */ (value)); - for (var i = 0; i < configs.length; i++) { - os.style.setConfigColor(configs[i], color, [os.style.StyleField.FILL]); - } - - os.command.FeatureFillColor.base(this, 'applyValue', configs, value); -}; - - -/** - * Set the label color - * @param {Object} configs The style config - * @param {string} value The value to apply - */ -os.command.FeatureFillColor.prototype.applyLabelValue = function(configs, value) { - var feature = /** @type {ol.Feature} */ (this.getFeature()); - feature.set(os.style.StyleField.LABEL_COLOR, value); - - for (var i = 0; i < configs.length; i++) { - configs[i][os.style.StyleField.LABEL_COLOR] = value; - } -}; - - -/** - * @inheritDoc - */ -os.command.FeatureFillColor.prototype.finish = function(configs) { - // dispatch the color change event on the source for the histogram - var feature = this.getFeature(); - - feature.dispatchEvent(new os.events.PropertyChangeEvent('colors')); - - os.command.FeatureFillColor.base(this, 'finish', configs); -}; diff --git a/src/os/command/feature/featurefillopacitycmd.js b/src/os/command/feature/featurefillopacitycmd.js deleted file mode 100644 index 56cb75fd6..000000000 --- a/src/os/command/feature/featurefillopacitycmd.js +++ /dev/null @@ -1,80 +0,0 @@ -goog.provide('os.command.FeatureFillOpacity'); - -goog.require('os.command.AbstractFeatureStyle'); -goog.require('os.events.PropertyChangeEvent'); -goog.require('os.metrics'); -goog.require('os.ui'); - - - -/** - * Changes the fill opacity of a feature - * @extends {os.command.AbstractFeatureStyle} - * @param {string} layerId - * @param {string} featureId - * @param {number} opacity - * @param {number=} opt_oldOpacity - * @constructor - */ -os.command.FeatureFillOpacity = function(layerId, featureId, opacity, opt_oldOpacity) { - os.command.FeatureFillOpacity.base(this, 'constructor', layerId, featureId, opacity, opt_oldOpacity); - this.title = 'Change Feature Fill Opacity'; - this.metricKey = os.metrics.Layer.FEATURE_FILL_OPACITY; - - this.value = opacity; -}; -goog.inherits(os.command.FeatureFillOpacity, os.command.AbstractFeatureStyle); - - -/** - * @type {number} - * @const - */ -os.command.FeatureFillOpacity.DEFAULT_OPACITY = os.style.DEFAULT_FILL_ALPHA; - - -/** - * @inheritDoc - */ -os.command.FeatureFillOpacity.prototype.getOldValue = function() { - var feature = this.getFeature(); - var config = /** @type {Array|Object|undefined} */ (this.getFeatureConfigs(feature)); - if (goog.isArray(config)) { - config = config[0]; - } - - if (config) { - var color = os.style.getConfigColor(config, true, os.style.StyleField.FILL); - return color[3]; - } else { - return os.command.FeatureFillOpacity.DEFAULT_OPACITY; - } -}; - - -/** - * @inheritDoc - */ -os.command.FeatureFillOpacity.prototype.applyValue = function(configs, value) { - var color; - for (var i = 0; i < configs.length; i++) { - color = os.style.getConfigColor(configs[i], true, os.style.StyleField.FILL); - color[3] = value; - os.style.setConfigColor(configs[i], color, [os.style.StyleField.FILL]); - } - - os.command.FeatureFillOpacity.base(this, 'applyValue', configs, value); -}; - - -/** - * @inheritDoc - */ -os.command.FeatureFillOpacity.prototype.finish = function(configs) { - // dispatch the color change event on the source for the histogram - var feature = this.getFeature(); - - feature.dispatchEvent(new os.events.PropertyChangeEvent('colors')); - - os.command.FeatureFillOpacity.base(this, 'finish', configs); -}; diff --git a/src/os/command/feature/featureopacitycmd.js b/src/os/command/feature/featureopacitycmd.js index 4b381096b..82c3bae56 100644 --- a/src/os/command/feature/featureopacitycmd.js +++ b/src/os/command/feature/featureopacitycmd.js @@ -14,13 +14,32 @@ goog.require('os.ui'); * @param {string} layerId * @param {string} featureId * @param {number} opacity - * @param {number=} opt_oldOpacity + * @param {number|null=} opt_oldOpacity + * @param {string=} opt_changeMode * @constructor */ -os.command.FeatureOpacity = function(layerId, featureId, opacity, opt_oldOpacity) { +os.command.FeatureOpacity = function(layerId, featureId, opacity, opt_oldOpacity, opt_changeMode) { + this.changeMode = opt_changeMode; os.command.FeatureOpacity.base(this, 'constructor', layerId, featureId, opacity, opt_oldOpacity); - this.title = 'Change Feature Opacity'; - this.metricKey = os.metrics.Layer.FEATURE_OPACITY; + + switch (this.changeMode) { + case os.command.FeatureOpacity.MODE.FILL: + this.title = 'Change Feature Fill Opacity'; + this.metricKey = os.metrics.Layer.FEATURE_FILL_OPACITY; + this.defaultOpacity = os.command.FeatureOpacity.DEFAULT_FILL_OPACITY; + break; + case os.command.FeatureOpacity.MODE.STROKE: + this.title = 'Change Feature Stroke Opacity'; + this.metricKey = os.metrics.Layer.FEATURE_STROKE_OPACITY; + this.defaultOpacity = os.command.FeatureOpacity.DEFAULT_OPACITY; + break; + default: + case os.command.FeatureOpacity.MODE.COMBINED: + this.title = 'Change Feature Opacity'; + this.metricKey = os.metrics.Layer.FEATURE_OPACITY; + this.defaultOpacity = os.command.FeatureOpacity.DEFAULT_OPACITY; + break; + } if (!opacity) { var feature = this.getFeature(); @@ -46,6 +65,20 @@ goog.inherits(os.command.FeatureOpacity, os.command.AbstractFeatureStyle); os.command.FeatureOpacity.DEFAULT_OPACITY = 1; +/** + * @type {number} + * @const + */ +os.command.FeatureOpacity.DEFAULT_FILL_OPACITY = 0; + + +os.command.FeatureOpacity.MODE = { + COMBINED: 'combined', + FILL: 'fill', + STROKE: 'stroke' +}; + + /** * @inheritDoc */ @@ -56,7 +89,27 @@ os.command.FeatureOpacity.prototype.getOldValue = function() { config = config[0]; } - return config ? os.style.getConfigOpacityColor(config) : os.command.FeatureOpacity.DEFAULT_OPACITY; + var ret = this.defaultOpacity; + + if (config) { + switch (this.changeMode) { + case os.command.FeatureOpacity.MODE.FILL: + var color = os.style.getConfigColor(config, true, os.style.StyleField.FILL); + ret = color[3]; + break; + case os.command.FeatureOpacity.MODE.STROKE: + var color = os.style.getConfigColor(config, true, os.style.StyleField.STROKE); + ret = color[3]; + break; + default: + case os.command.FeatureOpacity.MODE.COMBINED: + var color = os.style.getConfigColor(config, true); + ret = color[3]; + break; + } + } + + return ret; }; @@ -64,8 +117,36 @@ os.command.FeatureOpacity.prototype.getOldValue = function() { * @inheritDoc */ os.command.FeatureOpacity.prototype.applyValue = function(configs, value) { - for (var i = 0; i < configs.length; i++) { - os.style.setConfigOpacityColor(configs[i], value); + var color; + var colorValue; + var i; + + switch (this.changeMode) { + case os.command.FeatureOpacity.MODE.FILL: + for (i = 0; i < configs.length; i++) { + color = os.style.getConfigColor(configs[i], true, os.style.StyleField.FILL); + color[3] = value; + colorValue = os.style.toRgbaString(color); + os.style.setConfigColor(configs[i], colorValue, [os.style.StyleField.FILL]); + } + break; + case os.command.FeatureOpacity.MODE.STROKE: + for (i = 0; i < configs.length; i++) { + color = os.style.getConfigColor(configs[i], true, os.style.StyleField.STROKE); + color[3] = value; + colorValue = os.style.toRgbaString(color); + os.style.setConfigColor(configs[i], colorValue, [os.style.StyleField.STROKE, os.style.StyleField.IMAGE]); + } + break; + default: + case os.command.FeatureOpacity.MODE.COMBINED: + for (i = 0; i < configs.length; i++) { + color = os.style.getConfigColor(configs[i], true); + color[3] = value; + colorValue = os.style.toRgbaString(color); + os.style.setConfigColor(configs[i], colorValue); + } + break; } os.command.FeatureOpacity.base(this, 'applyValue', configs, value); diff --git a/src/os/command/feature/featurestrokecolorcmd.js b/src/os/command/feature/featurestrokecolorcmd.js deleted file mode 100644 index bb5e9bcda..000000000 --- a/src/os/command/feature/featurestrokecolorcmd.js +++ /dev/null @@ -1,123 +0,0 @@ -goog.provide('os.command.FeatureStrokeColor'); - -goog.require('os.command.AbstractFeatureStyle'); -goog.require('os.events.PropertyChangeEvent'); -goog.require('os.metrics'); - - - -/** - * Changes the stroke color of a feature - * @extends {os.command.AbstractFeatureStyle} - * @param {string} layerId - * @param {string} featureId - * @param {Array|string} color - * @param {(Array|string)=} opt_oldColor - * @constructor - */ -os.command.FeatureStrokeColor = function(layerId, featureId, color, opt_oldColor) { - os.command.FeatureStrokeColor.base(this, 'constructor', layerId, featureId, color, opt_oldColor); - this.title = 'Change Feature Stroke Color'; - this.metricKey = os.metrics.Layer.FEATURE_STROKE_COLOR; - - if (!color) { - var feature = this.getFeature(); - var config = /** @type {Object|undefined} */ (feature.get(os.style.StyleType.FEATURE)); - - if (config) { - if (goog.isArray(config)) { - config = config[0]; - } - var configColor = /** @type {Array|string|undefined} */ (os.style.getConfigColor(config)); - - if (configColor) { - color = os.color.toHexString(color); - } - } - } - - // Make sure the value is a string - this.value = os.style.toRgbaString(color); -}; -goog.inherits(os.command.FeatureStrokeColor, os.command.AbstractFeatureStyle); - - -/** - * @type {string} - * @const - */ -os.command.FeatureStrokeColor.DEFAULT_COLOR = 'rgba(255,255,255,1)'; - - -/** - * @inheritDoc - */ -os.command.FeatureStrokeColor.prototype.getOldValue = function() { - var feature = /** @type {ol.Feature} */ (this.getFeature()); - var config = /** @type {Array|Object|undefined} */ (this.getFeatureConfigs(feature)); - if (goog.isArray(config)) { - config = config[0]; - } - - if (config) { - return os.style.getConfigColor(config, false, os.style.StyleField.STROKE); - } else { - return os.command.FeatureStrokeColor.DEFAULT_COLOR; - } -}; - - -/** - * Gets the old label color - * @return {Array|string|undefined} - */ -os.command.FeatureStrokeColor.prototype.getLabelValue = function() { - var feature = /** @type {ol.Feature} */ (this.getFeature()); - var labelColor = /** @type {Array|string|undefined} */ (feature.get(os.style.StyleField.LABEL_COLOR)); - return labelColor ? labelColor : os.style.DEFAULT_LAYER_COLOR; -}; - - -/** - * @inheritDoc - */ -os.command.FeatureStrokeColor.prototype.applyValue = function(configs, value) { - var color = os.style.toRgbaString(/** @type {string} */ (value)); - for (var i = 0; i < configs.length; i++) { - os.style.setConfigColor(configs[i], color, [os.style.StyleField.STROKE, os.style.StyleField.IMAGE]); - } - - if (this.oldValue == this.getLabelValue()) { - this.applyLabelValue(configs, value); - } - - os.command.FeatureStrokeColor.base(this, 'applyValue', configs, value); -}; - - -/** - * Set the label color - * @param {Object} configs The style config - * @param {string} value The value to apply - */ -os.command.FeatureStrokeColor.prototype.applyLabelValue = function(configs, value) { - var feature = /** @type {ol.Feature} */ (this.getFeature()); - feature.set(os.style.StyleField.LABEL_COLOR, value); - - for (var i = 0; i < configs.length; i++) { - configs[i][os.style.StyleField.LABEL_COLOR] = value; - } -}; - - -/** - * @inheritDoc - */ -os.command.FeatureStrokeColor.prototype.finish = function(configs) { - // dispatch the color change event on the source for the histogram - var feature = this.getFeature(); - - feature.dispatchEvent(new os.events.PropertyChangeEvent('colors')); - - os.command.FeatureStrokeColor.base(this, 'finish', configs); -}; diff --git a/src/os/command/feature/featurestrokeopacitycmd.js b/src/os/command/feature/featurestrokeopacitycmd.js deleted file mode 100644 index 9714f840f..000000000 --- a/src/os/command/feature/featurestrokeopacitycmd.js +++ /dev/null @@ -1,75 +0,0 @@ -goog.provide('os.command.FeatureStrokeOpacity'); - -goog.require('os.command.AbstractFeatureStyle'); -goog.require('os.events.PropertyChangeEvent'); -goog.require('os.metrics'); -goog.require('os.ui'); - - - -/** - * Changes the stroke opacity of a feature - * @extends {os.command.AbstractFeatureStyle} - * @param {string} layerId - * @param {string} featureId - * @param {number} opacity - * @param {number=} opt_oldOpacity - * @constructor - */ -os.command.FeatureStrokeOpacity = function(layerId, featureId, opacity, opt_oldOpacity) { - os.command.FeatureStrokeOpacity.base(this, 'constructor', layerId, featureId, opacity, opt_oldOpacity); - this.title = 'Change Feature Stroke Opacity'; - this.metricKey = os.metrics.Layer.FEATURE_STROKE_OPACITY; - - if (!opacity) { - var feature = this.getFeature(); - var config = /** @type {Object|undefined} */ (feature.get(os.style.StyleType.FEATURE)); - - if (config) { - if (goog.isArray(config)) { - config = config[0]; - } - opacity = /** @type {number} */ (os.style.getConfigOpacityColor(config)); - } - } - - this.value = opacity; -}; -goog.inherits(os.command.FeatureStrokeOpacity, os.command.AbstractFeatureStyle); - - -/** - * @type {number} - * @const - */ -os.command.FeatureStrokeOpacity.DEFAULT_OPACITY = 1; - - -/** - * @inheritDoc - */ -os.command.FeatureStrokeOpacity.prototype.getOldValue = function() { - var feature = /** @type {ol.Feature} */ (this.getFeature()); - var config = /** @type {Array|Object|undefined} */ (this.getFeatureConfigs(feature)); - if (goog.isArray(config)) { - config = config[0]; - } - - return config ? os.style.getConfigOpacityColor(config) : os.command.FeatureStrokeOpacity.DEFAULT_OPACITY; -}; - - -/** - * @inheritDoc - */ -os.command.FeatureStrokeOpacity.prototype.applyValue = function(configs, value) { - var color; - - for (var i = 0; i < configs.length; i++) { - color = os.style.getConfigColor(configs[i], true, os.style.StyleField.STROKE); - color[3] = value; - os.style.setConfigColor(configs[i], color, [os.style.StyleField.STROKE, os.style.StyleField.IMAGE]); - } - - os.command.FeatureStrokeOpacity.base(this, 'applyValue', configs, value); -}; diff --git a/src/os/command/vectorlayercolorcmd.js b/src/os/command/vectorlayercolorcmd.js index b1e3ac39f..10b73b2a4 100644 --- a/src/os/command/vectorlayercolorcmd.js +++ b/src/os/command/vectorlayercolorcmd.js @@ -16,18 +16,38 @@ goog.require('os.ui'); * @param {string} layerId * @param {Array|string} color * @param {(Array|string)=} opt_oldColor + * @param {string=} opt_changeMode * @constructor */ -os.command.VectorLayerColor = function(layerId, color, opt_oldColor) { +os.command.VectorLayerColor = function(layerId, color, opt_oldColor, opt_changeMode) { os.command.VectorLayerColor.base(this, 'constructor', layerId, color, opt_oldColor); - this.title = 'Change Color'; - this.metricKey = os.metrics.Layer.VECTOR_COLOR; + + this.changeMode = opt_changeMode; + + switch (this.changeMode) { + case os.command.VectorLayerColor.MODE.FILL: + this.title = 'Change Fill Color'; + this.metricKey = os.metrics.Layer.VECTOR_FILL_COLOR; + this.defaultColor = os.command.VectorLayerColor.DEFAULT_FILL_COLOR; + break; + case os.command.VectorLayerColor.MODE.STROKE: + this.title = 'Change Stroke Color'; + this.metricKey = os.metrics.Layer.VECTOR_STROKE_COLOR; + this.defaultColor = os.command.VectorLayerColor.DEFAULT_COLOR; + break; + default: + case os.command.VectorLayerColor.MODE.COMBINED: + this.title = 'Change Color'; + this.metricKey = os.metrics.Layer.VECTOR_COLOR; + this.defaultColor = os.command.VectorLayerColor.DEFAULT_COLOR; + break; + } if (!color) { var layer = /** @type {os.layer.Vector} */ (os.MapContainer.getInstance().getLayer(this.layerId)); if (layer) { var options = layer.getLayerOptions(); - color = /** @type {string} */ (options && options['baseColor'] || os.command.VectorLayerColor.DEFAULT_COLOR); + color = /** @type {string} */ (options && options['baseColor'] || this.defaultColor); } } @@ -44,12 +64,44 @@ goog.inherits(os.command.VectorLayerColor, os.command.AbstractVectorStyle); os.command.VectorLayerColor.DEFAULT_COLOR = 'rgba(255,255,255,1)'; +/** + * @type {string} + * @const + */ +os.command.VectorLayerColor.DEFAULT_FILL_COLOR = 'rgba(255,255,255,0)'; + + +os.command.VectorLayerColor.MODE = { + COMBINED: 'combined', + FILL: 'fill', + STROKE: 'stroke' +}; + /** * @inheritDoc */ os.command.VectorLayerColor.prototype.getOldValue = function() { var config = os.style.StyleManager.getInstance().getLayerConfig(this.layerId); - return config ? os.style.getConfigColor(config) : os.command.VectorLayerColor.DEFAULT_COLOR; + var ret; + + if (config) { + switch (this.changeMode) { + case os.command.VectorLayerColor.MODE.FILL: + ret = os.style.getConfigColor(config, false, os.style.StyleField.FILL); + break; + case os.command.VectorLayerColor.MODE.STROKE: + ret = os.style.getConfigColor(config, false, os.style.StyleField.STROKE); + break; + default: + case os.command.VectorLayerColor.MODE.COMBINED: + ret = os.style.getConfigColor(config); + break; + } + } else { + ret = this.defaultColor; + } + + return ret; }; @@ -58,19 +110,39 @@ os.command.VectorLayerColor.prototype.getOldValue = function() { */ os.command.VectorLayerColor.prototype.applyValue = function(config, value) { var color = os.style.toRgbaString(/** @type {string} */ (value)); - os.style.setConfigColor(config, color); - // Make sure the fill color and opacity are updated as well - if (config['fillColor']) { - config['fillColor'] = color; - } - if (config['fillOpacity'] !== undefined) { - var colorArray = os.color.toRgbArray(value); - config['fillOpacity'] = colorArray[3]; + switch (this.changeMode) { + case os.command.VectorLayerColor.MODE.FILL: + os.style.setConfigColor(config, color, [os.style.StyleField.FILL]); + + // Make sure the fill color and opacity are updated as well + if (config['fillColor']) { + config['fillColor'] = color; + } + break; + case os.command.VectorLayerColor.MODE.STROKE: + os.style.setConfigColor(config, color, + [os.style.StyleField.STROKE, os.style.StyleField.IMAGE]); + os.ui.adjustIconSet(this.layerId, color); + break; + default: + case os.command.VectorLayerColor.MODE.COMBINED: + os.style.setConfigColor(config, color); + + // Make sure the fill color and opacity are updated as well + if (config['fillColor']) { + config['fillColor'] = color; + } + if (config['fillOpacity'] !== undefined) { + var colorArray = os.color.toRgbArray(value); + config['fillOpacity'] = colorArray[3]; + } + + os.ui.adjustIconSet(this.layerId, color); + + break; } - os.ui.adjustIconSet(this.layerId, color); - os.command.VectorLayerColor.base(this, 'applyValue', config, value); }; diff --git a/src/os/command/vectorlayerfillcolorcmd.js b/src/os/command/vectorlayerfillcolorcmd.js deleted file mode 100644 index 98e4dc269..000000000 --- a/src/os/command/vectorlayerfillcolorcmd.js +++ /dev/null @@ -1,90 +0,0 @@ -goog.provide('os.command.VectorLayerFillColor'); - -goog.require('os.command.AbstractVectorStyle'); -goog.require('os.data.OSDataManager'); -goog.require('os.events.PropertyChangeEvent'); -goog.require('os.metrics'); -goog.require('os.source.PropertyChange'); -goog.require('os.ui'); - - - -/** - * Changes the fill color of a layer - * @extends {os.command.AbstractVectorStyle} - * @param {string} layerId - * @param {Array|string} color - * @param {(Array|string)=} opt_oldColor - * @constructor - */ -os.command.VectorLayerFillColor = function(layerId, color, opt_oldColor) { - os.command.VectorLayerFillColor.base(this, 'constructor', layerId, color, opt_oldColor); - this.title = 'Change Fill Color'; - this.metricKey = os.metrics.Layer.VECTOR_FILL_COLOR; - - if (!color) { - var layer = /** @type {os.layer.Vector} */ (os.MapContainer.getInstance().getLayer(this.layerId)); - if (layer) { - var options = layer.getLayerOptions(); - color = /** @type {string} */ (options && options['baseColor'] || os.command.VectorLayerFillColor.DEFAULT_COLOR); - } - } - - // make sure the value is a string - this.value = os.style.toRgbaString(color); -}; -goog.inherits(os.command.VectorLayerFillColor, os.command.AbstractVectorStyle); - - -/** - * @type {string} - * @const - */ -os.command.VectorLayerFillColor.DEFAULT_COLOR = 'rgba(255,255,255,0)'; - - -/** - * @inheritDoc - */ -os.command.VectorLayerFillColor.prototype.getOldValue = function() { - var config = os.style.StyleManager.getInstance().getLayerConfig(this.layerId); - - if (config) { - os.style.getConfigColor(config, false, os.style.StyleField.FILL); - } else { - return os.command.VectorLayerFillColor.DEFAULT_COLOR; - } -}; - - -/** - * @inheritDoc - */ -os.command.VectorLayerFillColor.prototype.applyValue = function(config, value) { - var color = os.style.toRgbaString(/** @type {string} */ (value)); - os.style.setConfigColor(config, color, [os.style.StyleField.FILL]); - - // Make sure the fill color and opacity are updated as well - if (config['fillColor']) { - config['fillColor'] = color; - } - - os.command.VectorLayerFillColor.base(this, 'applyValue', config, value); -}; - - -/** - * @inheritDoc - */ -os.command.VectorLayerFillColor.prototype.finish = function(config) { - // dispatch the color change event on the source for the histogram - var source = os.osDataManager.getSource(this.layerId); - source.dispatchEvent(new os.events.PropertyChangeEvent(os.source.PropertyChange.COLOR, this.value)); - - if (source instanceof os.source.Vector) { - // a color change on the layer should clear any color model on the source - source.setColorModel(null); - } - - os.command.VectorLayerFillColor.base(this, 'finish', config); -}; diff --git a/src/os/command/vectorlayerfillopacitycmd.js b/src/os/command/vectorlayerfillopacitycmd.js deleted file mode 100644 index e229852a3..000000000 --- a/src/os/command/vectorlayerfillopacitycmd.js +++ /dev/null @@ -1,69 +0,0 @@ -goog.provide('os.command.VectorLayerFillOpacity'); - -goog.require('os.command.AbstractVectorStyle'); -goog.require('os.events.PropertyChangeEvent'); -goog.require('os.metrics'); -goog.require('os.ui'); - - - -/** - * Changes the fill opacity of a feature - * @extends {os.command.AbstractVectorStyle} - * @param {string} layerId - * @param {number} opacity - * @param {number=} opt_oldOpacity - * @constructor - */ -os.command.VectorLayerFillOpacity = function(layerId, opacity, opt_oldOpacity) { - os.command.VectorLayerFillOpacity.base(this, 'constructor', layerId, opacity, opt_oldOpacity); - this.title = 'Change Fill Opacity'; - this.metricKey = os.metrics.Layer.VECTOR_FILL_OPACITY; - - this.value = opacity; -}; -goog.inherits(os.command.VectorLayerFillOpacity, os.command.AbstractVectorStyle); - - -/** - * @type {number} - * @const - */ -os.command.VectorLayerFillOpacity.DEFAULT_OPACITY = 0; - - -/** - * @inheritDoc - */ -os.command.VectorLayerFillOpacity.prototype.getOldValue = function() { - var config = os.style.StyleManager.getInstance().getLayerConfig(this.layerId); - return config ? os.style.getConfigOpacityColor(config) : os.command.VectorLayerFillOpacity.DEFAULT_OPACITY; -}; - - -/** - * @inheritDoc - */ -os.command.VectorLayerFillOpacity.prototype.applyValue = function(config, value) { - var color = os.style.getConfigColor(config, true, os.style.StyleField.FILL); - color[3] = value; - - var colorString = os.style.toRgbaString(color); - os.style.setConfigColor(config, colorString, [os.style.StyleField.FILL]); - config['fillColor'] = colorString; - config['fillOpacity'] = value; - - os.command.VectorLayerFillOpacity.base(this, 'applyValue', config, value); -}; - - -/** - * @inheritDoc - */ -os.command.VectorLayerFillOpacity.prototype.finish = function(config) { - // dispatch the color change event on the source for the histogram - var source = os.osDataManager.getSource(this.layerId); - source.dispatchEvent(new os.events.PropertyChangeEvent(os.source.PropertyChange.COLOR, this.value)); - - os.command.VectorLayerFillOpacity.base(this, 'finish', config); -}; diff --git a/src/os/command/vectorlayeropacitycmd.js b/src/os/command/vectorlayeropacitycmd.js index 9ac1d28e0..75b1896fe 100644 --- a/src/os/command/vectorlayeropacitycmd.js +++ b/src/os/command/vectorlayeropacitycmd.js @@ -15,16 +15,36 @@ goog.require('os.ui'); * @extends {os.command.AbstractVectorStyle} * @param {string} layerId * @param {number} opacity - * @param {number=} opt_oldOpacity + * @param {number|null=} opt_oldOpacity + * @param {string=} opt_changeMode * @constructor */ -os.command.VectorLayerOpacity = function(layerId, opacity, opt_oldOpacity) { +os.command.VectorLayerOpacity = function(layerId, opacity, opt_oldOpacity, opt_changeMode) { os.command.VectorLayerOpacity.base(this, 'constructor', layerId, opacity, opt_oldOpacity); - this.title = 'Change Opacity'; - this.metricKey = os.metrics.Layer.VECTOR_OPACITY; + + this.changeMode = opt_changeMode; + + switch (this.changeMode) { + case os.command.VectorLayerColor.MODE.FILL: + this.title = 'Change Fill Opacity'; + this.metricKey = os.metrics.Layer.VECTOR_FILL_OPACITY; + this.defaultOpacity = os.command.VectorLayerOpacity.DEFAULT_FILL_OPACITY; + break; + case os.command.VectorLayerColor.MODE.STROKE: + this.title = 'Change Stroke Opacity'; + this.metricKey = os.metrics.Layer.VECTOR_STROKE_OPACITY; + this.defaultOpacity = os.command.VectorLayerOpacity.DEFAULT_OPACITY; + break; + default: + case os.command.VectorLayerColor.MODE.COMBINED: + this.title = 'Change Opacity'; + this.metricKey = os.metrics.Layer.VECTOR_OPACITY; + this.defaultOpacity = os.command.VectorLayerOpacity.DEFAULT_OPACITY; + break; + } if (!opacity) { - opacity = os.command.VectorLayerOpacity.DEFAULT_OPACITY; + opacity = this.defaultOpacity; var layer = /** @type {os.layer.Vector} */ (os.MapContainer.getInstance().getLayer(this.layerId)); if (layer) { var options = layer.getLayerOptions(); @@ -44,12 +64,26 @@ goog.inherits(os.command.VectorLayerOpacity, os.command.AbstractVectorStyle); os.command.VectorLayerOpacity.DEFAULT_OPACITY = 1; +/** + * @type {number} + * @const + */ +os.command.VectorLayerOpacity.DEFAULT_FILL_OPACITY = 0; + + +os.command.VectorLayerOpacity.MODE = { + COMBINED: 'combined', + FILL: 'fill', + STROKE: 'stroke' +}; + + /** * @inheritDoc */ os.command.VectorLayerOpacity.prototype.getOldValue = function() { var config = os.style.StyleManager.getInstance().getLayerConfig(this.layerId); - return config ? os.style.getConfigColor(config) : os.command.VectorLayerOpacity.DEFAULT_OPACITY; + return config ? os.style.getConfigOpacityColor(config) : this.defaultOpacity; }; @@ -59,19 +93,43 @@ os.command.VectorLayerOpacity.prototype.getOldValue = function() { os.command.VectorLayerOpacity.prototype.applyValue = function(config, value) { var color = os.style.getConfigColor(config, true); color[3] = value; - var colorString = os.style.toRgbaString(color); - os.style.setConfigColor(config, colorString); - // Make sure the fill color and opacity are updated as well - if (config['fillColor']) { - config['fillColor'] = colorString; - } - if (config['fillOpacity'] !== undefined) { - config['fillOpacity'] = value; - } + switch (this.changeMode) { + case os.command.VectorLayerOpacity.MODE.FILL: + os.style.setConfigColor(config, colorString, [os.style.StyleField.FILL]); + + // Make sure the fill color and opacity are updated as well + if (config['fillColor']) { + config['fillColor'] = colorString; + } + if (config['fillOpacity'] !== undefined) { + config['fillOpacity'] = value; + } + + break; + case os.command.VectorLayerOpacity.MODE.STROKE: + os.style.setConfigColor(config, colorString, [os.style.StyleField.IMAGE, os.style.StyleField.STROKE]); + + os.ui.adjustIconSet(this.layerId, color); - os.ui.adjustIconSet(this.layerId, color); + break; + default: + case os.command.VectorLayerOpacity.MODE.COMBINED: + os.style.setConfigColor(config, colorString); + + // Make sure the fill color and opacity are updated as well + if (config['fillColor']) { + config['fillColor'] = colorString; + } + if (config['fillOpacity'] !== undefined) { + config['fillOpacity'] = value; + } + + os.ui.adjustIconSet(this.layerId, color); + + break; + } os.command.VectorLayerOpacity.base(this, 'applyValue', config, value); }; diff --git a/src/os/command/vectorlayerstrokecolorcmd.js b/src/os/command/vectorlayerstrokecolorcmd.js deleted file mode 100644 index ad86835be..000000000 --- a/src/os/command/vectorlayerstrokecolorcmd.js +++ /dev/null @@ -1,88 +0,0 @@ -goog.provide('os.command.VectorLayerStrokeColor'); - -goog.require('os.command.AbstractVectorStyle'); -goog.require('os.data.OSDataManager'); -goog.require('os.events.PropertyChangeEvent'); -goog.require('os.metrics'); -goog.require('os.source.PropertyChange'); -goog.require('os.ui'); - - - -/** - * Changes the stroke color of a layer - * @extends {os.command.AbstractVectorStyle} - * @param {string} layerId - * @param {Array|string} color - * @param {(Array|string)=} opt_oldColor - * @constructor - */ -os.command.VectorLayerStrokeColor = function(layerId, color, opt_oldColor) { - os.command.VectorLayerStrokeColor.base(this, 'constructor', layerId, color, opt_oldColor); - this.title = 'Change Stroke Color'; - this.metricKey = os.metrics.Layer.VECTOR_STROKE_COLOR; - - if (!color) { - var layer = /** @type {os.layer.Vector} */ (os.MapContainer.getInstance().getLayer(this.layerId)); - if (layer) { - var options = layer.getLayerOptions(); - color = /** @type {string} */ (options && options['baseColor'] || - os.command.VectorLayerStrokeColor.DEFAULT_COLOR); - } - } - - // make sure the value is a string - this.value = os.style.toRgbaString(color); -}; -goog.inherits(os.command.VectorLayerStrokeColor, os.command.AbstractVectorStyle); - - -/** - * @type {string} - * @const - */ -os.command.VectorLayerStrokeColor.DEFAULT_COLOR = 'rgba(255,255,255,1)'; - - -/** - * @inheritDoc - */ -os.command.VectorLayerStrokeColor.prototype.getOldValue = function() { - var config = os.style.StyleManager.getInstance().getLayerConfig(this.layerId); - - if (config) { - os.style.getConfigColor(config, false, os.style.StyleField.STROKE); - } else { - return os.command.VectorLayerFillColor.DEFAULT_COLOR; - } -}; - - -/** - * @inheritDoc - */ -os.command.VectorLayerStrokeColor.prototype.applyValue = function(config, value) { - var color = os.style.toRgbaString(/** @type {string} */ (value)); - - os.style.setConfigColor(config, color, [os.style.StyleField.STROKE, os.style.StyleField.IMAGE]); - os.ui.adjustIconSet(this.layerId, color); - - os.command.VectorLayerStrokeColor.base(this, 'applyValue', config, value); -}; - - -/** - * @inheritDoc - */ -os.command.VectorLayerStrokeColor.prototype.finish = function(config) { - // dispatch the color change event on the source for the histogram - var source = os.osDataManager.getSource(this.layerId); - source.dispatchEvent(new os.events.PropertyChangeEvent(os.source.PropertyChange.COLOR, this.value)); - - if (source instanceof os.source.Vector) { - // a color change on the layer should clear any color model on the source - source.setColorModel(null); - } - - os.command.VectorLayerStrokeColor.base(this, 'finish', config); -}; diff --git a/src/os/command/vectorlayerstrokeopacitycmd.js b/src/os/command/vectorlayerstrokeopacitycmd.js deleted file mode 100644 index 293b10be3..000000000 --- a/src/os/command/vectorlayerstrokeopacitycmd.js +++ /dev/null @@ -1,69 +0,0 @@ -goog.provide('os.command.VectorLayerStrokeOpacity'); - -goog.require('os.command.AbstractVectorStyle'); -goog.require('os.events.PropertyChangeEvent'); -goog.require('os.metrics'); -goog.require('os.ui'); - - - -/** - * Changes the stroke opacity of a feature - * @extends {os.command.AbstractVectorStyle} - * @param {string} layerId - * @param {number} opacity - * @param {number=} opt_oldOpacity - * @constructor - */ -os.command.VectorLayerStrokeOpacity = function(layerId, opacity, opt_oldOpacity) { - os.command.VectorLayerStrokeOpacity.base(this, 'constructor', layerId, opacity, opt_oldOpacity); - this.title = 'Change Stroke Opacity'; - this.metricKey = os.metrics.Layer.VECTOR_STROKE_OPACITY; - - this.value = opacity; -}; -goog.inherits(os.command.VectorLayerStrokeOpacity, os.command.AbstractVectorStyle); - - -/** - * @type {number} - * @const - */ -os.command.VectorLayerStrokeOpacity.DEFAULT_OPACITY = 1; - - -/** - * @inheritDoc - */ -os.command.VectorLayerStrokeOpacity.prototype.getOldValue = function() { - var config = os.style.StyleManager.getInstance().getLayerConfig(this.layerId); - return config ? os.style.getConfigOpacityColor(config) : os.command.VectorLayerStrokeOpacity.DEFAULT_OPACITY; -}; - - -/** - * @inheritDoc - */ -os.command.VectorLayerStrokeOpacity.prototype.applyValue = function(config, value) { - var color = os.style.getConfigColor(config, true, os.style.StyleField.IMAGE); - color[3] = value; - - var colorString = os.style.toRgbaString(color); - os.style.setConfigColor(config, colorString, [os.style.StyleField.IMAGE, os.style.StyleField.STROKE]); - - os.ui.adjustIconSet(this.layerId, color); - - os.command.VectorLayerStrokeOpacity.base(this, 'applyValue', config, value); -}; - - -/** - * @inheritDoc - */ -os.command.VectorLayerStrokeOpacity.prototype.finish = function(config) { - // dispatch the color change event on the source for the histogram - var source = os.osDataManager.getSource(this.layerId); - source.dispatchEvent(new os.events.PropertyChangeEvent(os.source.PropertyChange.COLOR, this.value)); - - os.command.VectorLayerStrokeOpacity.base(this, 'finish', config); -}; diff --git a/src/os/ui/layer/vectorlayerui.js b/src/os/ui/layer/vectorlayerui.js index 9dbcf1a90..2e71a3c80 100644 --- a/src/os/ui/layer/vectorlayerui.js +++ b/src/os/ui/layer/vectorlayerui.js @@ -4,14 +4,10 @@ goog.provide('os.ui.layer.vectorLayerUIDirective'); goog.require('goog.color'); goog.require('os.MapChange'); goog.require('os.array'); -goog.require('os.command.FeatureOpacity'); -goog.require('os.command.FeatureStrokeOpacity'); goog.require('os.command.LayerStyle'); goog.require('os.command.VectorLayerAutoRefresh'); goog.require('os.command.VectorLayerCenterShape'); goog.require('os.command.VectorLayerColor'); -goog.require('os.command.VectorLayerFillColor'); -goog.require('os.command.VectorLayerFillOpacity'); goog.require('os.command.VectorLayerIcon'); goog.require('os.command.VectorLayerLabel'); goog.require('os.command.VectorLayerLabelColor'); @@ -24,8 +20,6 @@ goog.require('os.command.VectorLayerShape'); goog.require('os.command.VectorLayerShowLabel'); goog.require('os.command.VectorLayerShowRotation'); goog.require('os.command.VectorLayerSize'); -goog.require('os.command.VectorLayerStrokeColor'); -goog.require('os.command.VectorLayerStrokeOpacity'); goog.require('os.command.VectorUniqueIdCmd'); goog.require('os.data.OSDataManager'); goog.require('os.defines'); @@ -354,7 +348,8 @@ os.ui.layer.VectorLayerUICtrl.prototype.onColorChange = function(event, value) { * @return {os.command.ICommand} */ function(layer) { - return new os.command.VectorLayerColor(layer.getId(), colorValue); + return new os.command.VectorLayerColor( + layer.getId(), colorValue, null, os.command.VectorLayerColor.MODE.COMBINED); }; this.createCommand(fn); @@ -366,7 +361,8 @@ os.ui.layer.VectorLayerUICtrl.prototype.onColorChange = function(event, value) { * @return {os.command.ICommand} */ function(layer) { - return new os.command.VectorLayerStrokeColor(layer.getId(), colorValue); + return new os.command.VectorLayerColor( + layer.getId(), colorValue, null, os.command.VectorLayerColor.MODE.STROKE); }; this.createCommand(fn2); @@ -380,7 +376,8 @@ os.ui.layer.VectorLayerUICtrl.prototype.onColorChange = function(event, value) { * @return {os.command.ICommand} */ function(layer) { - return new os.command.VectorLayerFillColor(layer.getId(), colorValue); + return new os.command.VectorLayerColor( + layer.getId(), colorValue, null, os.command.VectorLayerColor.MODE.FILL); }; this.createCommand(fn3); @@ -391,7 +388,8 @@ os.ui.layer.VectorLayerUICtrl.prototype.onColorChange = function(event, value) { * @return {os.command.ICommand} */ function(layer) { - return new os.command.VectorLayerStrokeColor(layer.getId(), colorValue); + return new os.command.VectorLayerColor( + layer.getId(), colorValue, null, os.command.VectorLayerColor.MODE.STROKE); }; this.createCommand(fn4); @@ -436,7 +434,8 @@ os.ui.layer.VectorLayerUICtrl.prototype.onFillColorChange = function(event, valu * @return {os.command.ICommand} */ function(layer) { - return new os.command.VectorLayerFillColor(layer.getId(), colorValue); + return new os.command.VectorLayerColor( + layer.getId(), colorValue, null, os.command.VectorLayerColor.MODE.FILL); }; this.createCommand(fn); @@ -498,13 +497,14 @@ os.ui.layer.VectorLayerUICtrl.prototype.onSliderStop = function(callback, key, e if (event.name == 'fillOpacity.slidestop') { var fn = - /** - * @param {os.layer.ILayer} layer - * @return {os.command.ICommand} - */ - function(layer) { - return new os.command.VectorLayerFillOpacity(layer.getId(), value); - }; + /** + * @param {os.layer.ILayer} layer + * @return {os.command.ICommand} + */ + function(layer) { + return new os.command.VectorLayerOpacity( + layer.getId(), value, null, os.command.VectorLayerOpacity.MODE.FILL); + }; this.createCommand(fn); } else if (this.scope['fillOpacity'] !== undefined && this.scope['opacity'] == this.scope['fillOpacity']) { @@ -525,7 +525,8 @@ os.ui.layer.VectorLayerUICtrl.prototype.onSliderStop = function(callback, key, e * @return {?os.command.ICommand} */ function(layer) { - return new os.command.VectorLayerStrokeOpacity(layer.getId(), value); + return new os.command.VectorLayerOpacity( + layer.getId(), value, null, os.command.VectorLayerOpacity.MODE.STROKE); }; this.createCommand(fn3); diff --git a/src/plugin/featureaction/ui/featurestyleactionconfig.js b/src/plugin/featureaction/ui/featurestyleactionconfig.js index 9105aa8c0..210db3f57 100644 --- a/src/plugin/featureaction/ui/featurestyleactionconfig.js +++ b/src/plugin/featureaction/ui/featurestyleactionconfig.js @@ -3,10 +3,6 @@ goog.provide('plugin.im.action.feature.ui.styleConfigDirective'); goog.require('goog.color'); goog.require('os.color'); -goog.require('os.command.FeatureColor'); -goog.require('os.command.FeatureFillColor'); -goog.require('os.command.FeatureFillOpacity'); -goog.require('os.command.FeatureOpacity'); goog.require('os.object'); goog.require('os.style'); goog.require('os.ui.Module'); diff --git a/src/plugin/file/kml/kmlnodelayerui.js b/src/plugin/file/kml/kmlnodelayerui.js index 096781f8d..573cdbb4e 100644 --- a/src/plugin/file/kml/kmlnodelayerui.js +++ b/src/plugin/file/kml/kmlnodelayerui.js @@ -3,8 +3,6 @@ goog.provide('plugin.file.kml.KMLNodeLayerUICtrl.UIEventType'); goog.provide('plugin.file.kml.kmlNodeLayerUIDirective'); goog.require('os.command.FeatureCenterShape'); goog.require('os.command.FeatureColor'); -goog.require('os.command.FeatureFillColor'); -goog.require('os.command.FeatureFillOpacity'); goog.require('os.command.FeatureIcon'); goog.require('os.command.FeatureLabel'); goog.require('os.command.FeatureLabelColor'); @@ -14,8 +12,6 @@ goog.require('os.command.FeatureOpacity'); goog.require('os.command.FeatureShape'); goog.require('os.command.FeatureShowLabel'); goog.require('os.command.FeatureSize'); -goog.require('os.command.FeatureStrokeColor'); -goog.require('os.command.FeatureStrokeOpacity'); goog.require('os.command.ParallelCommand'); goog.require('os.data.ColumnDefinition'); goog.require('os.ui.Module'); @@ -617,7 +613,7 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onColorChange = function(event, val * @return {os.command.ICommand} */ function(layerId, featureId) { - return new os.command.FeatureStrokeColor(layerId, featureId, colorValue); + return new os.command.FeatureColor(layerId, featureId, colorValue, null, os.command.FeatureColor.MODE.STROKE); }; this.createFeatureCommand(fn2); @@ -633,7 +629,7 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onColorChange = function(event, val * @return {os.command.ICommand} */ function(layerId, featureId) { - return new os.command.FeatureFillColor(layerId, featureId, colorValue); + return new os.command.FeatureColor(layerId, featureId, colorValue, null, os.command.FeatureColor.MODE.FILL); }; this.createFeatureCommand(fn3); @@ -645,7 +641,7 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onColorChange = function(event, val * @return {os.command.ICommand} */ function(layerId, featureId) { - return new os.command.FeatureStrokeColor(layerId, featureId, colorValue); + return new os.command.FeatureColor(layerId, featureId, colorValue, null, os.command.FeatureColor.MODE.STROKE); }; this.createFeatureCommand(fn4); @@ -672,7 +668,7 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onFillColorChange = function(event, * @return {os.command.ICommand} */ function(layerId, featureId) { - return new os.command.FeatureFillColor(layerId, featureId, colorValue); + return new os.command.FeatureColor(layerId, featureId, colorValue, null, os.command.FeatureColor.MODE.FILL); }; this.createFeatureCommand(fn); @@ -814,7 +810,7 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onOpacityChange = function(event, v * @return {os.command.ICommand} */ function(layerId, featureId) { - return new os.command.FeatureStrokeOpacity(layerId, featureId, value); + return new os.command.FeatureOpacity(layerId, featureId, value, null, os.command.FeatureOpacity.MODE.STROKE); }; this.createFeatureCommand(fn2); @@ -832,6 +828,7 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onOpacityChange = function(event, v */ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onFillOpacityChange = function(event, value) { event.stopPropagation(); + console.log('onFillOpacityChange', value); var fn = /** @@ -840,7 +837,7 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onFillOpacityChange = function(even * @return {os.command.ICommand} */ function(layerId, featureId) { - return new os.command.FeatureFillOpacity(layerId, featureId, value); + return new os.command.FeatureOpacity(layerId, featureId, value, null, os.command.FeatureOpacity.MODE.FILL); }; this.createFeatureCommand(fn); From c9db84c04f7e7194263cf055c7659f9e01d1211a Mon Sep 17 00:00:00 2001 From: Kevin Schmidt Date: Tue, 6 Aug 2019 11:29:40 -0600 Subject: [PATCH 06/28] fix(kml): export fill/stroke colors correctly for lines and polygons BREAKING CHANGE: This changes the behavior of `os.style.getConfigColor` when using a field hint. - If `config. === null`, return `null`. This allows disabling stroke/fill. - If `config..color` is defined, return the value. - Return `undefined` otherwise, indicating the field/color could not be found. --- src/os/command/feature/featureopacitycmd.js | 12 +- src/os/feature/feature.js | 94 +++-- src/os/layer/image.js | 4 +- src/os/layer/vector.js | 4 +- src/os/style/style.js | 35 +- src/os/ui/file/kml/abstractkmlexporter.js | 33 +- src/plugin/file/kml/kmlexporter.js | 12 +- src/plugin/file/kml/kmlnodelayerui.js | 8 +- src/plugin/file/kml/kmltreeexporter.js | 13 +- test/os/feature/feature.test.js | 119 ++++++ test/os/style/style.test.js | 391 ++++++++++++-------- 11 files changed, 490 insertions(+), 235 deletions(-) diff --git a/src/os/command/feature/featureopacitycmd.js b/src/os/command/feature/featureopacitycmd.js index 82c3bae56..4fb573d05 100644 --- a/src/os/command/feature/featureopacitycmd.js +++ b/src/os/command/feature/featureopacitycmd.js @@ -95,16 +95,22 @@ os.command.FeatureOpacity.prototype.getOldValue = function() { switch (this.changeMode) { case os.command.FeatureOpacity.MODE.FILL: var color = os.style.getConfigColor(config, true, os.style.StyleField.FILL); - ret = color[3]; + if (color) { + ret = color[3]; + } break; case os.command.FeatureOpacity.MODE.STROKE: var color = os.style.getConfigColor(config, true, os.style.StyleField.STROKE); - ret = color[3]; + if (color) { + ret = color[3]; + } break; default: case os.command.FeatureOpacity.MODE.COMBINED: var color = os.style.getConfigColor(config, true); - ret = color[3]; + if (color) { + ret = color[3]; + } break; } } diff --git a/src/os/feature/feature.js b/src/os/feature/feature.js index 0f7d92019..b3c15db87 100644 --- a/src/os/feature/feature.js +++ b/src/os/feature/feature.js @@ -737,41 +737,57 @@ os.feature.getSource = function(feature, opt_layer) { * * @param {ol.Feature} feature The feature. * @param {os.source.ISource=} opt_source The source containing the feature, or null to ignore source color. - * @param {*=} opt_default The default color. - * @return {*} The color. + * @param {(Array|string)=} opt_default The default color, `null` to indicate no color. + * @param {os.style.StyleField=} opt_colorField The style field to use in locating the color. + * @return {Array|string} The color. * * @suppress {accessControls} To allow direct access to feature metadata. */ -os.feature.getColor = function(feature, opt_source, opt_default) { +os.feature.getColor = function(feature, opt_source, opt_default, opt_colorField) { + var defaultColor = opt_default !== undefined ? opt_default : os.style.DEFAULT_LAYER_COLOR; + if (feature) { - var color = /** @type {string|undefined} */ (feature.values_[os.data.RecordField.COLOR]); + var color; + + if (!opt_colorField) { + // ignore the feature color override if a specific config color field was provided + color = /** @type {string|undefined} */ (feature.values_[os.data.RecordField.COLOR]); + } - if (!color) { + if (color !== defaultColor) { // check the layer config to see if it's replacing feature styles var layerConfig = os.style.getLayerConfig(feature); if (layerConfig && layerConfig[os.style.StyleField.REPLACE_STYLE]) { - color = /** @type {string|undefined} */ (os.style.getConfigColor(layerConfig, false)); + color = os.style.getConfigColor(layerConfig, false, opt_colorField); } } - if (!color) { + if (color !== defaultColor) { var featureConfig = /** @type {Array|Object|undefined} */ (feature.values_[os.style.StyleType.FEATURE]); if (featureConfig) { if (Array.isArray(featureConfig)) { for (var i = 0; !color && i < featureConfig.length; i++) { - color = os.style.getConfigColor(featureConfig[i]) || undefined; + color = os.style.getConfigColor(featureConfig[i], false, opt_colorField); + + // stop on the first color found, allowing null if set as the default + if (color || (color === null && defaultColor === null)) { + break; + } } } else { - color = os.style.getConfigColor(featureConfig) || undefined; + color = os.style.getConfigColor(featureConfig, false, opt_colorField); } } } - if (color) { - return color; + if (color || (color === null && defaultColor === null)) { + // if the default color was provided as null, allow returning that as the color + return /** @type {Array|string} */ (color); } else if (opt_source) { + // fall back on the source color return opt_source.getColor(); } else if (opt_source !== null) { + // try to locate the source var source = os.feature.getSource(feature); if (source) { return source.getColor(); @@ -779,7 +795,7 @@ os.feature.getColor = function(feature, opt_source, opt_default) { } } - return opt_default !== undefined ? opt_default : os.style.DEFAULT_LAYER_COLOR; + return defaultColor; }; @@ -787,49 +803,25 @@ os.feature.getColor = function(feature, opt_source, opt_default) { * Get the fill color of a feature. * @param {ol.Feature} feature The feature. * @param {os.source.ISource=} opt_source The source containing the feature, or null to ignore source color. - * @param {*=} opt_default The default color. - * @return {*} The color. - * - * @suppress {accessControls} To allow direct access to feature metadata. + * @param {(Array|string)=} opt_default The default color. + * @return {Array|string} The color. */ os.feature.getFillColor = function(feature, opt_source, opt_default) { - if (feature) { - var color = /** @type {string|undefined} */ (feature.values_[os.data.RecordField.COLOR]); - - if (!color) { - // check the layer config to see if it's replacing feature styles - var layerConfig = os.style.getLayerConfig(feature); - if (layerConfig && layerConfig[os.style.StyleField.REPLACE_STYLE]) { - color = /** @type {string|undefined} */ (os.style.getConfigColor(layerConfig, false, os.style.StyleField.FILL)); - } - } - - if (!color) { - var featureConfig = /** @type {Array|Object|undefined} */ (feature.values_[os.style.StyleType.FEATURE]); - if (featureConfig) { - if (Array.isArray(featureConfig)) { - for (var i = 0; !color && i < featureConfig.length; i++) { - color = os.style.getConfigColor(featureConfig[i], false, os.style.StyleField.FILL) || undefined; - } - } else { - color = os.style.getConfigColor(featureConfig, false, os.style.StyleField.FILL) || undefined; - } - } - } + // default to null to indicate no fill + return os.feature.getColor(feature, opt_source, opt_default || null, os.style.StyleField.FILL); +}; - if (color) { - return color; - } else if (opt_source) { - return opt_source.getColor(); - } else if (opt_source !== null) { - var source = os.feature.getSource(feature); - if (source) { - return source.getColor(); - } - } - } - return opt_default !== undefined ? opt_default : os.style.DEFAULT_LAYER_COLOR; +/** + * Get the stroke color of a feature. + * @param {ol.Feature} feature The feature. + * @param {os.source.ISource=} opt_source The source containing the feature, or null to ignore source color. + * @param {(Array|string)=} opt_default The default color. + * @return {Array|string} The color. + */ +os.feature.getStrokeColor = function(feature, opt_source, opt_default) { + // default to null to indicate no stroke + return os.feature.getColor(feature, opt_source, opt_default || null, os.style.StyleField.STROKE); }; diff --git a/src/os/layer/image.js b/src/os/layer/image.js index d5b004d70..fbae97402 100644 --- a/src/os/layer/image.js +++ b/src/os/layer/image.js @@ -411,7 +411,9 @@ os.layer.Image.prototype.getIcons = function() { if (config) { var color = os.style.getConfigColor(config, true); - return os.ui.createIconSet(this.getId(), this.getSVGSet(), this.getFASet(), color); + if (color) { + return os.ui.createIconSet(this.getId(), this.getSVGSet(), this.getFASet(), color); + } } return this.getIconSet().join(''); diff --git a/src/os/layer/vector.js b/src/os/layer/vector.js index dc8b5198a..b4bc37a9e 100644 --- a/src/os/layer/vector.js +++ b/src/os/layer/vector.js @@ -381,7 +381,9 @@ os.layer.Vector.prototype.getIcons = function() { if (config) { var color = os.style.getConfigColor(config, true); - return os.ui.createIconSet(this.getId(), this.getSVGSet(), this.getFASet(), color); + if (color) { + return os.ui.createIconSet(this.getId(), this.getSVGSet(), this.getFASet(), color); + } } return this.getIconSet().join(''); diff --git a/src/os/style/style.js b/src/os/style/style.js index 3d1d642f1..f3a745264 100644 --- a/src/os/style/style.js +++ b/src/os/style/style.js @@ -563,19 +563,32 @@ os.style.STYLE_COLOR_FIELDS_ = ['image', 'fill', 'stroke']; * * @param {Object} config The configuration to search for a color * @param {boolean=} opt_array If the color should be returned as an rgb array - * @param {(os.style.StyleField|string)=} opt_colorFieldHint A hint to where to find the color to use. - * @return {?(string|Array)} The color or null if none was found + * @param {os.style.StyleField=} opt_colorField The style field to use in locating the color. + * @return {Array|string|undefined} The color, or undefined if not found. Returns `null` if a style field was + * provided and the field was `null`. */ -os.style.getConfigColor = function(config, opt_array, opt_colorFieldHint) { +os.style.getConfigColor = function(config, opt_array, opt_colorField) { if (config) { - if (opt_colorFieldHint && - config[opt_colorFieldHint] && - config[opt_colorFieldHint][os.style.StyleField.COLOR] != null) { - return opt_array ? os.color.toRgbArray(config[opt_colorFieldHint][os.style.StyleField.COLOR]) : - config[opt_colorFieldHint][os.style.StyleField.COLOR]; + // + // if a specific color field was provided, return: + // - null (no color) if the field is null + // - config..color if defined + // - undefined (no color found) + // + // otherwise: + // - return config.color if defined + // - search all color fields for the color + // + if (opt_colorField) { + if (config[opt_colorField] === null) { + return null; + } else if (config[opt_colorField] && config[opt_colorField][os.style.StyleField.COLOR] != null) { + return opt_array ? os.color.toRgbArray(config[opt_colorField][os.style.StyleField.COLOR]) : + config[opt_colorField][os.style.StyleField.COLOR]; + } } else if (config[os.style.StyleField.COLOR] != null) { return opt_array ? os.color.toRgbArray(config[os.style.StyleField.COLOR]) : - config[os.style.StyleField.COLOR]; + config[os.style.StyleField.COLOR]; } else { for (var i = 0; i < os.style.STYLE_COLOR_FIELDS_.length; i++) { var key = os.style.STYLE_COLOR_FIELDS_[i]; @@ -590,7 +603,7 @@ os.style.getConfigColor = function(config, opt_array, opt_colorFieldHint) { } } - return null; + return undefined; }; @@ -1405,7 +1418,7 @@ os.style.createFeatureStyle = function(feature, baseConfig, opt_layerConfig) { // use label override color color = ol.color.asArray(opt_layerConfig[os.style.StyleField.LABEL_COLOR]); } else { - color = ol.color.asArray(os.style.getConfigColor(featureConfig)); + color = ol.color.asArray(os.style.getConfigColor(featureConfig) || os.style.DEFAULT_LAYER_COLOR); } color[3] *= opacity; labelStyle.text_.fill_.color_ = ol.color.toString(color); diff --git a/src/os/ui/file/kml/abstractkmlexporter.js b/src/os/ui/file/kml/abstractkmlexporter.js index 401f64a80..40e6458db 100644 --- a/src/os/ui/file/kml/abstractkmlexporter.js +++ b/src/os/ui/file/kml/abstractkmlexporter.js @@ -725,11 +725,13 @@ os.ui.file.kml.AbstractKMLExporter.prototype.addGeometryNode = function(item, no * @param {T} item The item * @param {string} styleId The style id * @param {string} color The item color - * @param {string} fillColor The item fill color + * @param {?string} fillColor The item fill color + * @param {?string} strokeColor The item fill color * @param {os.ui.file.kml.Icon=} opt_icon The item icon * @protected */ -os.ui.file.kml.AbstractKMLExporter.prototype.createStyle = function(item, styleId, color, fillColor, opt_icon) { +os.ui.file.kml.AbstractKMLExporter.prototype.createStyle = function(item, styleId, color, fillColor, strokeColor, + opt_icon) { var styleEl = os.xml.createElementNS('Style', this.kmlNS, this.doc, undefined, { 'id': styleId }); @@ -764,14 +766,14 @@ os.ui.file.kml.AbstractKMLExporter.prototype.createStyle = function(item, styleI os.xml.appendElementNS('color', this.kmlNS, iconStyleEl, color); } - // all styles should define a line/poly style var lineStyleEl = os.xml.appendElementNS('LineStyle', this.kmlNS, styleEl); - os.xml.appendElementNS('color', this.kmlNS, lineStyleEl, color); + os.xml.appendElementNS('color', this.kmlNS, lineStyleEl, strokeColor || color); os.xml.appendElementNS('width', this.kmlNS, lineStyleEl, 2); var polyStyleEl = os.xml.appendElementNS('PolyStyle', this.kmlNS, styleEl); - os.xml.appendElementNS('color', this.kmlNS, polyStyleEl, fillColor); - os.xml.appendElementNS('fill', this.kmlNS, polyStyleEl, 1); + os.xml.appendElementNS('color', this.kmlNS, polyStyleEl, fillColor || color); + os.xml.appendElementNS('fill', this.kmlNS, polyStyleEl, fillColor ? 1 : 0); + os.xml.appendElementNS('outline', this.kmlNS, polyStyleEl, strokeColor ? 1 : 0); var firstFolder = this.kmlDoc.querySelector('Folder'); if (firstFolder) { @@ -812,12 +814,22 @@ os.ui.file.kml.AbstractKMLExporter.prototype.getColor = function(item) {}; * Get the fill color of an item. This should return an ABGR string that can be dropped directly into the KML. * @abstract * @param {T} item The item - * @return {string} The item's fill color as an ABGR string + * @return {?string} The item's fill color as an ABGR string * @protected */ os.ui.file.kml.AbstractKMLExporter.prototype.getFillColor = function(item) {}; +/** + * Get the stroke color of an item. This should return an ABGR string that can be dropped directly into the KML. + * @abstract + * @param {T} item The item + * @return {?string} The item's stroke color as an ABGR string + * @protected + */ +os.ui.file.kml.AbstractKMLExporter.prototype.getStrokeColor = function(item) {}; + + /** * Get the type of KML element represented by the item. * @@ -1012,6 +1024,11 @@ os.ui.file.kml.AbstractKMLExporter.prototype.getStyleId = function(item) { styleParts.push(fillColor); } + var strokeColor = this.getStrokeColor(item); + if (this.useItemColor || type == os.ui.file.kml.StyleType.DEFAULT) { + styleParts.push(strokeColor); + } + var icon = type == os.ui.file.kml.StyleType.DEFAULT ? undefined : this.getIcon(item); if (type == os.ui.file.kml.StyleType.ICON && this.useItemIcon) { // override the default icon with the item's icon @@ -1029,7 +1046,7 @@ os.ui.file.kml.AbstractKMLExporter.prototype.getStyleId = function(item) { styleId = styleParts.join('-'); if (!(styleId in this.styles_)) { - this.createStyle(item, styleId, color, fillColor, icon); + this.createStyle(item, styleId, color, fillColor, strokeColor, icon); } return styleId; diff --git a/src/plugin/file/kml/kmlexporter.js b/src/plugin/file/kml/kmlexporter.js index 79907e2aa..8f98278f6 100644 --- a/src/plugin/file/kml/kmlexporter.js +++ b/src/plugin/file/kml/kmlexporter.js @@ -96,12 +96,16 @@ plugin.file.kml.KMLExporter.prototype.getColor = function(item) { */ plugin.file.kml.KMLExporter.prototype.getFillColor = function(item) { var itemColor = os.feature.getFillColor(item, this.getSource_(item)); + return itemColor ? os.style.toAbgrString(itemColor) : null; +}; - if (!itemColor || (typeof itemColor != 'string' && !goog.isArray(itemColor))) { - itemColor = os.style.DEFAULT_LAYER_COLOR; - } - return os.style.toAbgrString(itemColor); +/** + * @inheritDoc + */ +plugin.file.kml.KMLExporter.prototype.getStrokeColor = function(item) { + var itemColor = os.feature.getStrokeColor(item, this.getSource_(item)); + return itemColor ? os.style.toAbgrString(itemColor) : null; }; diff --git a/src/plugin/file/kml/kmlnodelayerui.js b/src/plugin/file/kml/kmlnodelayerui.js index 573cdbb4e..e1de667a3 100644 --- a/src/plugin/file/kml/kmlnodelayerui.js +++ b/src/plugin/file/kml/kmlnodelayerui.js @@ -225,7 +225,9 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.getFillOpacity = function() { config = config[0]; } var color = os.style.getConfigColor(config, true, os.style.StyleField.FILL); - opacity = color[3]; + if (color) { + opacity = color[3]; + } } } } @@ -415,7 +417,9 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.getOpacity = function() { } var color = os.style.getConfigColor(config, true, os.style.StyleField.STROKE); - opacity = color[3]; + if (color) { + opacity = color[3]; + } } } } diff --git a/src/plugin/file/kml/kmltreeexporter.js b/src/plugin/file/kml/kmltreeexporter.js index 4fcba9e47..1395a9f8a 100644 --- a/src/plugin/file/kml/kmltreeexporter.js +++ b/src/plugin/file/kml/kmltreeexporter.js @@ -99,11 +99,16 @@ plugin.file.kml.KMLTreeExporter.prototype.getColor = function(item) { */ plugin.file.kml.KMLTreeExporter.prototype.getFillColor = function(item) { var featureColor = os.feature.getFillColor(item.getFeature()); - if (!featureColor || (typeof featureColor != 'string' && !goog.isArray(featureColor))) { - featureColor = os.style.DEFAULT_LAYER_COLOR; - } + return featureColor ? os.style.toAbgrString(featureColor) : null; +}; - return os.style.toAbgrString(featureColor); + +/** + * @inheritDoc + */ +plugin.file.kml.KMLTreeExporter.prototype.getStrokeColor = function(item) { + var featureColor = os.feature.getStrokeColor(item.getFeature()); + return featureColor ? os.style.toAbgrString(featureColor) : null; }; diff --git a/test/os/feature/feature.test.js b/test/os/feature/feature.test.js index 02f1ae6e0..4f3a52a41 100644 --- a/test/os/feature/feature.test.js +++ b/test/os/feature/feature.test.js @@ -391,5 +391,124 @@ describe('os.feature', function() { feature.set('TITLE', 'test4'); expect(os.feature.getTitle(feature)).toBe('test4'); }); + + it('should get a color from a feature', function() { + + }); + + it('should get a fill color from a feature', function() { + var feature = new ol.Feature(); + var testColor = 'rgba(0,255,0,1)'; + var featureConfig1 = {}; + var featureConfig2 = { + fill: null + }; + + // defaults to null (no fill) when no feature provided + expect(os.feature.getFillColor(null)).toBeNull(); + // unless a default color was provided + expect(os.feature.getFillColor(null, undefined, os.style.DEFAULT_LAYER_COLOR)).toBe(os.style.DEFAULT_LAYER_COLOR); + + // defaults to null (no fill) + expect(os.feature.getFillColor(feature)).toBeNull(); + + // ignores feature base color override + feature.set(os.data.RecordField.COLOR, testColor); + expect(os.feature.getFillColor(feature)).toBeNull(); + + // empty config returns null + feature.set(os.style.StyleType.FEATURE, featureConfig1); + expect(os.feature.getFillColor(feature)).toBeNull(); + + // should not return the stroke/image color + featureConfig1.stroke = { + color: testColor, + width: 2 + }; + featureConfig1.image = { + color: testColor + }; + expect(os.feature.getFillColor(feature)).toBeNull(); + + // should not return the base config color + featureConfig1.color = testColor; + expect(os.feature.getFillColor(feature)).toBeNull(); + + // unless the fill is explicitly null + featureConfig1.fill = null; + expect(os.feature.getFillColor(feature)).toBeNull(); + + // gets the fill color + featureConfig1.fill = { + color: testColor + }; + expect(os.feature.getFillColor(feature)).toBe(testColor); + + // gets null from the first config + feature.set(os.style.StyleType.FEATURE, [featureConfig2, featureConfig1]); + expect(os.feature.getFillColor(feature)).toBeNull(); + + // gets the fill color from the second config + featureConfig2.fill = undefined; + expect(os.feature.getFillColor(feature)).toBe(testColor); + }); + + it('should get a stroke color from a feature', function() { + var feature = new ol.Feature(); + var testColor = 'rgba(0,255,0,1)'; + var featureConfig1 = {}; + var featureConfig2 = { + stroke: null + }; + + // defaults to null (no stroke) when no feature provided + expect(os.feature.getStrokeColor(null)).toBeNull(); + // unless a default color was provided + expect(os.feature.getStrokeColor(null, undefined, os.style.DEFAULT_LAYER_COLOR)) + .toBe(os.style.DEFAULT_LAYER_COLOR); + + // defaults to null (no stroke) + expect(os.feature.getStrokeColor(feature)).toBeNull(); + + // ignores feature base color override + feature.set(os.data.RecordField.COLOR, testColor); + expect(os.feature.getStrokeColor(feature)).toBeNull(); + + // empty config returns null + feature.set(os.style.StyleType.FEATURE, featureConfig1); + expect(os.feature.getStrokeColor(feature)).toBeNull(); + + // should not return the fill/image color + featureConfig1.fill = { + color: testColor + }; + featureConfig1.image = { + color: testColor + }; + expect(os.feature.getStrokeColor(feature)).toBeNull(); + + // should not return the base config color + featureConfig1.color = testColor; + expect(os.feature.getStrokeColor(feature)).toBeNull(); + + // unless the stroke is explicitly null + featureConfig1.stroke = null; + expect(os.feature.getStrokeColor(feature)).toBeNull(); + + // gets the stroke color + featureConfig1.stroke = { + color: testColor, + width: 2 + }; + expect(os.feature.getStrokeColor(feature)).toBe(testColor); + + // gets null from the first config + feature.set(os.style.StyleType.FEATURE, [featureConfig2, featureConfig1]); + expect(os.feature.getStrokeColor(feature)).toBeNull(); + + // gets the stroke color from the second config + featureConfig2.stroke = undefined; + expect(os.feature.getStrokeColor(feature)).toBe(testColor); + }); }); }); diff --git a/test/os/style/style.test.js b/test/os/style/style.test.js index f0d86f0bc..a66e022e4 100644 --- a/test/os/style/style.test.js +++ b/test/os/style/style.test.js @@ -84,186 +84,277 @@ describe('os.style', function() { }); expect(os.style.getConfigIcon(config).path).toBe('newvalue'); }); -}); -describe('os.style.createFeatureStyle', function() { - var base; - var layer; - var opacity = 0.25; - - // base style opacity (0.99) should be multiplied by the feature opacity (0.25) - var featureRgba = 'rgba(0,255,100,0.2475)'; - var labelRgba = 'rgba(0,123,123,0.2475)'; - - beforeEach(function() { - base = { - 'image': { - 'type': 'circle', - 'radius': 2, - 'fill': { - 'color': 'rgba(0,255,100,0.99)' - } - }, - 'stroke': { - 'width': '3', - 'color': 'rgba(0,255,100,0.99)' - } + describe('os.style.getConfigColor', function() { + var testColor = 'rgba(12,34,56,.5)'; + var testColorArray = os.color.toRgbArray(testColor); + var colorConfig = { + color: testColor }; - - layer = { - 'image': { - 'type': 'circle', - 'radius': 3, - 'fill': { - 'color': 'rgba(0,255,100,0.99)' - } - }, - 'text': { - 'fill': { - 'color': 'rgba(0,255,0,0.99)' - } - }, - 'labelColor': 'rgba(0,123,123,0.99)', - 'labels': [{'column': 'some_field', 'showColumn': 'true'}] + var fillConfig = { + fill: colorConfig + }; + var imageConfig = { + image: colorConfig + }; + var strokeConfig = { + stroke: colorConfig + }; + var nullFillConfig = { + fill: null + }; + var nullImageConfig = { + image: null + }; + var nullStrokeConfig = { + stroke: null + }; + var undefinedFillConfig = { + fill: undefined + }; + var undefinedImageConfig = { + image: undefined + }; + var undefinedStrokeConfig = { + stroke: undefined }; - }); - it('should never ever modify the incoming config parameters', function() { - var baseExpected = JSON.stringify(base); - var layerExpected = JSON.stringify(layer); + it('should get the color from a config using default fields', function() { + expect(os.style.getConfigColor(null)).toBeUndefined(); + expect(os.style.getConfigColor({})).toBeUndefined(); - var feature = new ol.Feature(); - feature.set(os.style.StyleType.FEATURE, base); + expect(os.style.getConfigColor(colorConfig)).toBe(testColor); + expect(os.style.getConfigColor(fillConfig)).toBe(testColor); + expect(os.style.getConfigColor(imageConfig)).toBe(testColor); + expect(os.style.getConfigColor(strokeConfig)).toBe(testColor); + }); + + it('should get the color from a config using the array parameter', function() { + expect(os.style.getConfigColor(colorConfig, false)).toEqual(testColor); + expect(os.style.getConfigColor(fillConfig, false)).toEqual(testColor); + expect(os.style.getConfigColor(imageConfig, false)).toEqual(testColor); + expect(os.style.getConfigColor(strokeConfig, false)).toEqual(testColor); - expect(JSON.stringify(base)).toBe(baseExpected); - expect(JSON.stringify(layer)).toBe(layerExpected); + expect(os.style.getConfigColor(colorConfig, true)).toEqual(testColorArray); + expect(os.style.getConfigColor(fillConfig, true)).toEqual(testColorArray); + expect(os.style.getConfigColor(imageConfig, true)).toEqual(testColorArray); + expect(os.style.getConfigColor(strokeConfig, true)).toEqual(testColorArray); + }); + + it('should get the color from a config using a field hint parameter', function() { + // hint doesn't exist in config + expect(os.style.getConfigColor(colorConfig, undefined, os.style.StyleField.FILL)).toBeUndefined(); + expect(os.style.getConfigColor(imageConfig, undefined, os.style.StyleField.FILL)).toBeUndefined(); + expect(os.style.getConfigColor(strokeConfig, undefined, os.style.StyleField.FILL)).toBeUndefined(); + + expect(os.style.getConfigColor(colorConfig, undefined, os.style.StyleField.STROKE)).toBeUndefined(); + expect(os.style.getConfigColor(fillConfig, undefined, os.style.StyleField.STROKE)).toBeUndefined(); + expect(os.style.getConfigColor(imageConfig, undefined, os.style.StyleField.STROKE)).toBeUndefined(); + + expect(os.style.getConfigColor(colorConfig, undefined, os.style.StyleField.IMAGE)).toBeUndefined(); + expect(os.style.getConfigColor(fillConfig, undefined, os.style.StyleField.IMAGE)).toBeUndefined(); + expect(os.style.getConfigColor(strokeConfig, undefined, os.style.StyleField.IMAGE)).toBeUndefined(); + + // hint is defined in config + expect(os.style.getConfigColor(fillConfig, false, os.style.StyleField.FILL)).toBe(testColor); + expect(os.style.getConfigColor(imageConfig, false, os.style.StyleField.IMAGE)).toBe(testColor); + expect(os.style.getConfigColor(strokeConfig, false, os.style.StyleField.STROKE)).toBe(testColor); + + expect(os.style.getConfigColor(fillConfig, true, os.style.StyleField.FILL)).toEqual(testColorArray); + expect(os.style.getConfigColor(imageConfig, true, os.style.StyleField.IMAGE)).toEqual(testColorArray); + expect(os.style.getConfigColor(strokeConfig, true, os.style.StyleField.STROKE)).toEqual(testColorArray); + + // hint is undefined in config + expect(os.style.getConfigColor(undefinedFillConfig, undefined, os.style.StyleField.FILL)).toBeUndefined(); + expect(os.style.getConfigColor(undefinedImageConfig, undefined, os.style.StyleField.IMAGE)).toBeUndefined(); + expect(os.style.getConfigColor(undefinedStrokeConfig, undefined, os.style.StyleField.STROKE)).toBeUndefined(); + + // hint is null in config + expect(os.style.getConfigColor(nullFillConfig, undefined, os.style.StyleField.FILL)).toBeNull(); + expect(os.style.getConfigColor(nullImageConfig, undefined, os.style.StyleField.IMAGE)).toBeNull(); + expect(os.style.getConfigColor(nullStrokeConfig, undefined, os.style.StyleField.STROKE)).toBeNull(); + }); }); - it('should create styles with a new opacity value', function() { - var feature = new ol.Feature(); - feature.set(os.style.StyleType.FEATURE, base); - feature.set(os.style.StyleField.OPACITY, opacity); - feature.set('some_field', 'test'); + describe('os.style.createFeatureStyle', function() { + var base; + var layer; + var opacity = 0.25; + + // base style opacity (0.99) should be multiplied by the feature opacity (0.25) + var featureRgba = 'rgba(0,255,100,0.2475)'; + var labelRgba = 'rgba(0,123,123,0.2475)'; + + beforeEach(function() { + base = { + 'image': { + 'type': 'circle', + 'radius': 2, + 'fill': { + 'color': 'rgba(0,255,100,0.99)' + } + }, + 'stroke': { + 'width': '3', + 'color': 'rgba(0,255,100,0.99)' + } + }; + + layer = { + 'image': { + 'type': 'circle', + 'radius': 3, + 'fill': { + 'color': 'rgba(0,255,100,0.99)' + } + }, + 'text': { + 'fill': { + 'color': 'rgba(0,255,0,0.99)' + } + }, + 'labelColor': 'rgba(0,123,123,0.99)', + 'labels': [{'column': 'some_field', 'showColumn': 'true'}] + }; + }); + + it('should never ever modify the incoming config parameters', function() { + var baseExpected = JSON.stringify(base); + var layerExpected = JSON.stringify(layer); - var style = os.style.createFeatureStyle(feature, base, layer); + var feature = new ol.Feature(); + feature.set(os.style.StyleType.FEATURE, base); - // check all the colors and verify the rgba value - expect(style.length).toBe(2); - expect(style[0].image_.fill_.color_).toBe(featureRgba); - expect(style[0].stroke_.color_).toBe(featureRgba); - expect(style[1].text_.fill_.color_).toBe(labelRgba); + expect(JSON.stringify(base)).toBe(baseExpected); + expect(JSON.stringify(layer)).toBe(layerExpected); + }); + it('should create styles with a new opacity value', function() { + var feature = new ol.Feature(); + feature.set(os.style.StyleType.FEATURE, base); + feature.set(os.style.StyleField.OPACITY, opacity); + feature.set('some_field', 'test'); - // attempt the same again with an empty base config - // to make sure no exceptions are thrown - feature = new ol.Feature(); - feature.set(os.style.StyleType.FEATURE, {}); - feature.set(os.style.StyleField.OPACITY, opacity); - feature.set('some_field', 'test'); + var style = os.style.createFeatureStyle(feature, base, layer); - var style = os.style.createFeatureStyle(feature, {}, layer); + // check all the colors and verify the rgba value + expect(style.length).toBe(2); + expect(style[0].image_.fill_.color_).toBe(featureRgba); + expect(style[0].stroke_.color_).toBe(featureRgba); + expect(style[1].text_.fill_.color_).toBe(labelRgba); - // check all the colors and verify the rgba value - expect(style.length).toBe(2); - }); -}); -describe('os.style.mergeConfig', function() { - it('should merge basic style configs', function() { - var from = { - 'string': 'This is a test', - 'number': 1, - 'boolean': true - }; + // attempt the same again with an empty base config + // to make sure no exceptions are thrown + feature = new ol.Feature(); + feature.set(os.style.StyleType.FEATURE, {}); + feature.set(os.style.StyleField.OPACITY, opacity); + feature.set('some_field', 'test'); - var to = {}; + var style = os.style.createFeatureStyle(feature, {}, layer); - os.style.mergeConfig(from, to); - expect(to).toEqual(from); - expect(to).not.toBe(from); + // check all the colors and verify the rgba value + expect(style.length).toBe(2); + }); }); - it('should merge nested style configs', function() { - var from = { - 'nested': { - 'string': 'test', + describe('os.style.mergeConfig', function() { + it('should merge basic style configs', function() { + var from = { + 'string': 'This is a test', 'number': 1, 'boolean': true - }, - 'string': 'This is a test', - 'number': 2, - 'boolean': false - }; - - var to = {}; - os.style.mergeConfig(from, to); - expect(to).toEqual(from); - }); - - it('should overwrite when merging', function() { - var from = { - 'nested': { - 'egg': 2 - }, - 'string': 'test', - 'number': 1, - 'boolean': true - }; - - var toMergeAll = { - 'nested': { - 'egg': 1 - }, - 'string': 'mergeAll', - 'number': 0, - 'boolean': false, - 'other': 'no change' - }; + }; - os.style.mergeConfig(from, toMergeAll); - expect(toMergeAll).toEqual(ol.obj.assign({}, toMergeAll, from)); + var to = {}; - var toMergeSome = { - 'string': 'mergeSome', - 'number': -1 - }; - - os.style.mergeConfig(from, toMergeSome); - expect(toMergeSome).toEqual(from); + os.style.mergeConfig(from, to); + expect(to).toEqual(from); + expect(to).not.toBe(from); + }); - var toMergeSomeNested = { - 'nested': {}, - 'string': 'mergeSomeNested' - }; + it('should merge nested style configs', function() { + var from = { + 'nested': { + 'string': 'test', + 'number': 1, + 'boolean': true + }, + 'string': 'This is a test', + 'number': 2, + 'boolean': false + }; + + var to = {}; + os.style.mergeConfig(from, to); + expect(to).toEqual(from); + }); - os.style.mergeConfig(from, toMergeSomeNested); - expect(toMergeSomeNested).toEqual(from); - }); + it('should overwrite when merging', function() { + var from = { + 'nested': { + 'egg': 2 + }, + 'string': 'test', + 'number': 1, + 'boolean': true + }; + + var toMergeAll = { + 'nested': { + 'egg': 1 + }, + 'string': 'mergeAll', + 'number': 0, + 'boolean': false, + 'other': 'no change' + }; + + os.style.mergeConfig(from, toMergeAll); + expect(toMergeAll).toEqual(ol.obj.assign({}, toMergeAll, from)); + + var toMergeSome = { + 'string': 'mergeSome', + 'number': -1 + }; + + os.style.mergeConfig(from, toMergeSome); + expect(toMergeSome).toEqual(from); + + var toMergeSomeNested = { + 'nested': {}, + 'string': 'mergeSomeNested' + }; + + os.style.mergeConfig(from, toMergeSomeNested); + expect(toMergeSomeNested).toEqual(from); + }); - it('should use null for deletions', function() { - var from = {'value': null}; + it('should use null for deletions', function() { + var from = {'value': null}; - var to = {'value': {'color': 'red'}}; + var to = {'value': {'color': 'red'}}; - os.style.mergeConfig(from, to); - expect(to).toEqual(from); + os.style.mergeConfig(from, to); + expect(to).toEqual(from); - var newAddition = {'value': {'color': 'blue'}}; + var newAddition = {'value': {'color': 'blue'}}; - os.style.mergeConfig(newAddition, to); - expect(to).toEqual(newAddition); - }); + os.style.mergeConfig(newAddition, to); + expect(to).toEqual(newAddition); + }); - it('should use undefined for inheritence', function() { - // we've already tested implicit undefined above, so test explicit undefined - var to = {'value': undefined}; - var from = {'value': 1}; - os.style.mergeConfig(from, to); - expect(to).toEqual(from); - - var to = {'stroke': undefined}; - var from = {'stroke': {'color': 'red'}}; - os.style.mergeConfig(from, to); - expect(to).toEqual(from); + it('should use undefined for inheritence', function() { + // we've already tested implicit undefined above, so test explicit undefined + var to = {'value': undefined}; + var from = {'value': 1}; + os.style.mergeConfig(from, to); + expect(to).toEqual(from); + + var to = {'stroke': undefined}; + var from = {'stroke': {'color': 'red'}}; + os.style.mergeConfig(from, to); + expect(to).toEqual(from); + }); }); }); From 7e4f07c602aebad432d3e0f3487328bcc64a3d56 Mon Sep 17 00:00:00 2001 From: Kevin Wilson Date: Wed, 7 Aug 2019 16:19:55 -0600 Subject: [PATCH 07/28] fix(fillstyle): hide the fill controls for points and lines --- src/os/command/feature/featurecolorcmd.js | 6 +- src/os/command/feature/featureopacitycmd.js | 6 +- src/os/command/vectorlayercolorcmd.js | 6 +- src/os/command/vectorlayeropacitycmd.js | 21 ++- src/os/ui/featureedit.js | 48 ++++++- src/plugin/file/kml/kmlnodelayerui.js | 143 +++++++++++++------- 6 files changed, 157 insertions(+), 73 deletions(-) diff --git a/src/os/command/feature/featurecolorcmd.js b/src/os/command/feature/featurecolorcmd.js index cd9315c73..bbcbf1e8e 100644 --- a/src/os/command/feature/featurecolorcmd.js +++ b/src/os/command/feature/featurecolorcmd.js @@ -33,8 +33,8 @@ os.command.FeatureColor = function(layerId, featureId, color, opt_oldColor, opt_ this.metricKey = os.metrics.Layer.FEATURE_STROKE_COLOR; this.defaultColor = os.command.FeatureColor.DEFAULT_COLOR; break; - default: case os.command.FeatureColor.MODE.COMBINED: + default: this.title = 'Change Feature Color'; this.metricKey = os.metrics.Layer.FEATURE_COLOR; this.defaultColor = os.command.FeatureColor.DEFAULT_COLOR; @@ -103,8 +103,8 @@ os.command.FeatureColor.prototype.getOldValue = function() { case os.command.FeatureColor.MODE.STROKE: ret = os.style.getConfigColor(config, false, os.style.StyleField.STROKE); break; - default: case os.command.FeatureColor.MODE.COMBINED: + default: ret = os.style.getConfigColor(config); break; } @@ -147,8 +147,8 @@ os.command.FeatureColor.prototype.applyValue = function(configs, value) { this.applyLabelValue(configs, value); } break; - default: case os.command.FeatureColor.MODE.COMBINED: + default: for (var i = 0; i < configs.length; i++) { os.style.setConfigColor(configs[i], color); } diff --git a/src/os/command/feature/featureopacitycmd.js b/src/os/command/feature/featureopacitycmd.js index 4fb573d05..ef83b3760 100644 --- a/src/os/command/feature/featureopacitycmd.js +++ b/src/os/command/feature/featureopacitycmd.js @@ -33,8 +33,8 @@ os.command.FeatureOpacity = function(layerId, featureId, opacity, opt_oldOpacity this.metricKey = os.metrics.Layer.FEATURE_STROKE_OPACITY; this.defaultOpacity = os.command.FeatureOpacity.DEFAULT_OPACITY; break; - default: case os.command.FeatureOpacity.MODE.COMBINED: + default: this.title = 'Change Feature Opacity'; this.metricKey = os.metrics.Layer.FEATURE_OPACITY; this.defaultOpacity = os.command.FeatureOpacity.DEFAULT_OPACITY; @@ -105,8 +105,8 @@ os.command.FeatureOpacity.prototype.getOldValue = function() { ret = color[3]; } break; - default: case os.command.FeatureOpacity.MODE.COMBINED: + default: var color = os.style.getConfigColor(config, true); if (color) { ret = color[3]; @@ -144,8 +144,8 @@ os.command.FeatureOpacity.prototype.applyValue = function(configs, value) { os.style.setConfigColor(configs[i], colorValue, [os.style.StyleField.STROKE, os.style.StyleField.IMAGE]); } break; - default: case os.command.FeatureOpacity.MODE.COMBINED: + default: for (i = 0; i < configs.length; i++) { color = os.style.getConfigColor(configs[i], true); color[3] = value; diff --git a/src/os/command/vectorlayercolorcmd.js b/src/os/command/vectorlayercolorcmd.js index 10b73b2a4..107fd451e 100644 --- a/src/os/command/vectorlayercolorcmd.js +++ b/src/os/command/vectorlayercolorcmd.js @@ -35,8 +35,8 @@ os.command.VectorLayerColor = function(layerId, color, opt_oldColor, opt_changeM this.metricKey = os.metrics.Layer.VECTOR_STROKE_COLOR; this.defaultColor = os.command.VectorLayerColor.DEFAULT_COLOR; break; - default: case os.command.VectorLayerColor.MODE.COMBINED: + default: this.title = 'Change Color'; this.metricKey = os.metrics.Layer.VECTOR_COLOR; this.defaultColor = os.command.VectorLayerColor.DEFAULT_COLOR; @@ -92,8 +92,8 @@ os.command.VectorLayerColor.prototype.getOldValue = function() { case os.command.VectorLayerColor.MODE.STROKE: ret = os.style.getConfigColor(config, false, os.style.StyleField.STROKE); break; - default: case os.command.VectorLayerColor.MODE.COMBINED: + default: ret = os.style.getConfigColor(config); break; } @@ -125,8 +125,8 @@ os.command.VectorLayerColor.prototype.applyValue = function(config, value) { [os.style.StyleField.STROKE, os.style.StyleField.IMAGE]); os.ui.adjustIconSet(this.layerId, color); break; - default: case os.command.VectorLayerColor.MODE.COMBINED: + default: os.style.setConfigColor(config, color); // Make sure the fill color and opacity are updated as well diff --git a/src/os/command/vectorlayeropacitycmd.js b/src/os/command/vectorlayeropacitycmd.js index 75b1896fe..312846c5a 100644 --- a/src/os/command/vectorlayeropacitycmd.js +++ b/src/os/command/vectorlayeropacitycmd.js @@ -35,8 +35,8 @@ os.command.VectorLayerOpacity = function(layerId, opacity, opt_oldOpacity, opt_c this.metricKey = os.metrics.Layer.VECTOR_STROKE_OPACITY; this.defaultOpacity = os.command.VectorLayerOpacity.DEFAULT_OPACITY; break; - default: case os.command.VectorLayerColor.MODE.COMBINED: + default: this.title = 'Change Opacity'; this.metricKey = os.metrics.Layer.VECTOR_OPACITY; this.defaultOpacity = os.command.VectorLayerOpacity.DEFAULT_OPACITY; @@ -91,12 +91,15 @@ os.command.VectorLayerOpacity.prototype.getOldValue = function() { * @inheritDoc */ os.command.VectorLayerOpacity.prototype.applyValue = function(config, value) { - var color = os.style.getConfigColor(config, true); - color[3] = value; - var colorString = os.style.toRgbaString(color); + var color; + var colorString; switch (this.changeMode) { case os.command.VectorLayerOpacity.MODE.FILL: + color = os.style.getConfigColor(config, true, os.style.StyleField.FILL); + color[3] = value; + colorString = os.style.toRgbaString(color); + os.style.setConfigColor(config, colorString, [os.style.StyleField.FILL]); // Make sure the fill color and opacity are updated as well @@ -109,13 +112,21 @@ os.command.VectorLayerOpacity.prototype.applyValue = function(config, value) { break; case os.command.VectorLayerOpacity.MODE.STROKE: + color = os.style.getConfigColor(config, true, os.style.StyleField.STROKE); + color[3] = value; + colorString = os.style.toRgbaString(color); + os.style.setConfigColor(config, colorString, [os.style.StyleField.IMAGE, os.style.StyleField.STROKE]); os.ui.adjustIconSet(this.layerId, color); break; - default: case os.command.VectorLayerOpacity.MODE.COMBINED: + default: + color = os.style.getConfigColor(config, true); + color[3] = value; + colorString = os.style.toRgbaString(color); + os.style.setConfigColor(config, colorString); // Make sure the fill color and opacity are updated as well diff --git a/src/os/ui/featureedit.js b/src/os/ui/featureedit.js index 6911cf307..9a0bf1f84 100644 --- a/src/os/ui/featureedit.js +++ b/src/os/ui/featureedit.js @@ -478,6 +478,11 @@ os.ui.FeatureEditCtrl = function($scope, $element, $timeout) { this.previewFeature = feature; this.originalProperties_ = feature.getProperties(); + if (!this.isPolygon()) { + delete this['fillColor']; + delete this['fillOpacity']; + } + if (this.originalProperties_) { // we don't care about or want these sticking around, so remove them delete this.originalProperties_[os.style.StyleType.SELECT]; @@ -773,6 +778,25 @@ os.ui.FeatureEditCtrl.prototype.isEllipse = function() { }; +/** + * If a polygon is selected. + * + * @return {boolean} + * @export + */ +os.ui.FeatureEditCtrl.prototype.isPolygon = function() { + var geometry = this.previewFeature.getGeometry(); + + if (geometry) { + var type = geometry.getType(); + + return type == ol.geom.GeometryType.POLYGON || type == ol.geom.GeometryType.MULTI_POLYGON; + } else { + return false; + } +}; + + /** * If a line or polygon is selected. * @@ -949,9 +973,17 @@ os.ui.FeatureEditCtrl.prototype.createPreviewFeature = function() { 'alt': this['altitude'] }; } + + delete this['fillColor']; + delete this['fillOpacity']; } else { // not a point, so disable geometry edit this.originalGeometry = geometry; + + if (geometry instanceof ol.geom.LineString) { + delete this['fillColor']; + delete this['fillOpacity']; + } } // default feature to show the name field @@ -1030,10 +1062,16 @@ os.ui.FeatureEditCtrl.prototype.loadFromFeature = function(feature) { this['centerIcon'] = icon; } + // Make sure we have a fill color and opacity for polygons, and don't have them otherwise if (config['fill'] && config['fill']['color']) { - this['fillColor'] = os.color.toHexString(config['fill']['color']); - var opacity = os.color.toRgbArray(config['fill']['color']); - this['fillOpacity'] = opacity[3]; + if (this.isPolygon()) { + this['fillColor'] = os.color.toHexString(config['fill']['color']); + var opacity = os.color.toRgbArray(config['fill']['color']); + this['fillOpacity'] = opacity[3]; + } else { + delete this['fillColor']; + delete this['fillOpacity']; + } } var lineDash = os.style.getConfigLineDash(config); @@ -1791,10 +1829,6 @@ os.ui.FeatureEditCtrl.updateFeatureStyle = function(feature) { config['stroke']['width'] = config['stroke']['width'] || size; config['stroke']['lineDash'] = lineDash; - // set fill for lines/polygons on the base config - config['fill'] = config['fill'] || {}; - config['fill']['color'] = os.style.toRgbaString(config['fill']['color'] || color); - // drop opacity to 0 if the shape style is set to 'None' if (shape === os.style.ShapeType.NONE) { os.style.setConfigOpacityColor(config, 0); diff --git a/src/plugin/file/kml/kmlnodelayerui.js b/src/plugin/file/kml/kmlnodelayerui.js index e1de667a3..2280149f3 100644 --- a/src/plugin/file/kml/kmlnodelayerui.js +++ b/src/plugin/file/kml/kmlnodelayerui.js @@ -138,9 +138,12 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.getProperties = function() { plugin.file.kml.KMLNodeLayerUICtrl.prototype.initUI = function() { plugin.file.kml.KMLNodeLayerUICtrl.base(this, 'initUI'); - if (this.scope) { + if (this.scope && this.isFeatureFillable()) { this.scope['fillColor'] = this.getFillColor(); this.scope['fillOpacity'] = this.getFillOpacity(); + } else { + delete this.scope['fillColor']; + delete this.scope['fillOpacity']; } }; @@ -584,71 +587,87 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onColorChange = function(event, val var colorValue = os.color.toRgbArray(value); colorValue[3] = this.scope['opacity']; - // Determine if we are changing both stroke and fill entirely, or keeping opacities separate, or only affecting stroke - var strokeColorArr = os.color.toRgbArray(this.scope['color']); - strokeColorArr[3] = this.scope['opacity']; - var strokeColorValue = os.style.toRgbaString(strokeColorArr); - var fillColorArr = os.color.toRgbArray(this.scope['fillColor']); - fillColorArr[3] = this.scope['fillOpacity']; - var fillColorValue = os.style.toRgbaString(fillColorArr); - var color = os.color.toHexString(this.scope['color']); - var fillColor = os.color.toHexString(this.scope['fillColor']); - - this.scope['color'] = os.color.toHexString(colorValue); + // Do we have fill color/opacity to consider? + if (this.scope['fillColor'] !== undefined && this.scope['fillOpacity'] !== undefined) { + // Determine if we are changing both stroke and fill entirely, or keeping opacities separate, or only affecting stroke + var strokeColorArr = os.color.toRgbArray(this.scope['color']); + strokeColorArr[3] = this.scope['opacity']; + var strokeColorValue = os.style.toRgbaString(strokeColorArr); + var fillColorArr = os.color.toRgbArray(this.scope['fillColor']); + fillColorArr[3] = this.scope['fillOpacity']; + var fillColorValue = os.style.toRgbaString(fillColorArr); + var color = os.color.toHexString(this.scope['color']); + var fillColor = os.color.toHexString(this.scope['fillColor']); + + this.scope['color'] = os.color.toHexString(colorValue); + + if (strokeColorValue == fillColorValue) { + var fn = + /** + * @param {string} layerId + * @param {string} featureId + * @return {os.command.ICommand} + */ + function(layerId, featureId) { + return new os.command.FeatureColor(layerId, featureId, colorValue); + }; - if (strokeColorValue == fillColorValue) { - var fn = - /** - * @param {string} layerId - * @param {string} featureId - * @return {os.command.ICommand} - */ - function(layerId, featureId) { - return new os.command.FeatureColor(layerId, featureId, colorValue); - }; + this.createFeatureCommand(fn); + } else if (color == fillColor) { + // We run these separately so that they retain the different opacities + var fn2 = + /** + * @param {string} layerId + * @param {string} featureId + * @return {os.command.ICommand} + */ + function(layerId, featureId) { + return new os.command.FeatureColor(layerId, featureId, colorValue, null, os.command.FeatureColor.MODE.STROKE); + }; - this.createFeatureCommand(fn); - } else if (color == fillColor) { - // We run these separately so that they retain the different opacities - var fn2 = - /** - * @param {string} layerId - * @param {string} featureId - * @return {os.command.ICommand} - */ - function(layerId, featureId) { - return new os.command.FeatureColor(layerId, featureId, colorValue, null, os.command.FeatureColor.MODE.STROKE); - }; + this.createFeatureCommand(fn2); - this.createFeatureCommand(fn2); + // Use the fill's opacity instead of the stroke's opacity + colorValue[3] = this.scope['fillOpacity']; + this.scope['fillColor'] = os.style.toRgbaString(colorValue); - // Use the fill's opacity instead of the stroke's opacity - colorValue[3] = this.scope['fillOpacity']; - this.scope['fillColor'] = os.style.toRgbaString(colorValue); + var fn3 = + /** + * @param {string} layerId + * @param {string} featureId + * @return {os.command.ICommand} + */ + function(layerId, featureId) { + return new os.command.FeatureColor(layerId, featureId, colorValue, null, os.command.FeatureColor.MODE.FILL); + }; - var fn3 = - /** - * @param {string} layerId - * @param {string} featureId - * @return {os.command.ICommand} - */ - function(layerId, featureId) { - return new os.command.FeatureColor(layerId, featureId, colorValue, null, os.command.FeatureColor.MODE.FILL); - }; + this.createFeatureCommand(fn3); + } else { + var fn4 = + /** + * @param {string} layerId + * @param {string} featureId + * @return {os.command.ICommand} + */ + function(layerId, featureId) { + return new os.command.FeatureColor(layerId, featureId, colorValue, null, os.command.FeatureColor.MODE.STROKE); + }; - this.createFeatureCommand(fn3); + this.createFeatureCommand(fn4); + } } else { - var fn4 = + // We are not taking fill into consideration + var fn5 = /** * @param {string} layerId * @param {string} featureId * @return {os.command.ICommand} */ function(layerId, featureId) { - return new os.command.FeatureColor(layerId, featureId, colorValue, null, os.command.FeatureColor.MODE.STROKE); + return new os.command.FeatureColor(layerId, featureId, colorValue); }; - this.createFeatureCommand(fn4); + this.createFeatureCommand(fn5); } }; @@ -832,7 +851,6 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onOpacityChange = function(event, v */ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onFillOpacityChange = function(event, value) { event.stopPropagation(); - console.log('onFillOpacityChange', value); var fn = /** @@ -1092,6 +1110,27 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.isFeatureDynamic = function() { }; +/** + * If the feature is fillable, which means it should show fill controls + * + * @return {boolean} + * @export + */ +plugin.file.kml.KMLNodeLayerUICtrl.prototype.isFeatureFillable = function() { + var features = this.getFeatures(); + var feature = features.length > 0 ? features[0] : null; + if (feature) { + var geometry = feature.getGeometry(); + + if (geometry instanceof ol.geom.Polygon || geometry instanceof ol.geom.MultiPolygon) { + return true; + } + } + + return false; +}; + + /** * Leave the rotation choices to the Place Add/Edit dialog since it is more involved * From a819e1d30438851244ec9fed71dae2d28bfba1dd Mon Sep 17 00:00:00 2001 From: Kevin Wilson Date: Mon, 12 Aug 2019 10:55:07 -0600 Subject: [PATCH 08/28] fix(fillstyle): using existing functions for geometry checks --- src/os/ui/featureedit.js | 5 ++--- src/plugin/file/kml/kmlnodelayerui.js | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/os/ui/featureedit.js b/src/os/ui/featureedit.js index 9a0bf1f84..75e5c1d52 100644 --- a/src/os/ui/featureedit.js +++ b/src/os/ui/featureedit.js @@ -15,6 +15,7 @@ goog.require('ol.geom.Point'); goog.require('os.MapContainer'); goog.require('os.action.EventType'); goog.require('os.data.ColumnDefinition'); +goog.require('os.geo'); goog.require('os.map'); goog.require('os.math.Units'); goog.require('os.ol.feature'); @@ -788,9 +789,7 @@ os.ui.FeatureEditCtrl.prototype.isPolygon = function() { var geometry = this.previewFeature.getGeometry(); if (geometry) { - var type = geometry.getType(); - - return type == ol.geom.GeometryType.POLYGON || type == ol.geom.GeometryType.MULTI_POLYGON; + return os.geo.isGeometryPolygonal(geometry); } else { return false; } diff --git a/src/plugin/file/kml/kmlnodelayerui.js b/src/plugin/file/kml/kmlnodelayerui.js index 2280149f3..9f9c11b29 100644 --- a/src/plugin/file/kml/kmlnodelayerui.js +++ b/src/plugin/file/kml/kmlnodelayerui.js @@ -14,6 +14,7 @@ goog.require('os.command.FeatureShowLabel'); goog.require('os.command.FeatureSize'); goog.require('os.command.ParallelCommand'); goog.require('os.data.ColumnDefinition'); +goog.require('os.geo'); goog.require('os.ui.Module'); goog.require('os.ui.layer.VectorLayerUICtrl'); goog.require('os.ui.layer.iconStyleControlsDirective'); @@ -1122,9 +1123,7 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.isFeatureFillable = function() { if (feature) { var geometry = feature.getGeometry(); - if (geometry instanceof ol.geom.Polygon || geometry instanceof ol.geom.MultiPolygon) { - return true; - } + return os.geo.isGeometryPolygonal(geometry); } return false; From bf5a9a7a9c20f5443357aca6bc1d54873913cc4e Mon Sep 17 00:00:00 2001 From: Kevin Schmidt Date: Tue, 13 Aug 2019 08:34:57 -0600 Subject: [PATCH 09/28] fix(kml): reuse existing event and fix plugin creep into os --- .../feature/abstractfeaturestylecmd.js | 4 ++- src/plugin/file/kml/kmlnodelayerui.js | 30 ++++++++----------- src/plugin/file/kml/ui/kmlui.js | 4 +-- 3 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/os/command/feature/abstractfeaturestylecmd.js b/src/os/command/feature/abstractfeaturestylecmd.js index 0d7842db9..7375733f1 100644 --- a/src/os/command/feature/abstractfeaturestylecmd.js +++ b/src/os/command/feature/abstractfeaturestylecmd.js @@ -1,5 +1,7 @@ goog.provide('os.command.AbstractFeatureStyle'); + goog.require('goog.events.Event'); +goog.require('os.action.EventType'); goog.require('os.command.AbstractStyle'); goog.require('os.command.ICommand'); goog.require('os.command.State'); @@ -67,7 +69,7 @@ os.command.AbstractFeatureStyle.prototype.applyValue = function(configs, value) * @inheritDoc */ os.command.AbstractFeatureStyle.prototype.finish = function(configs) { - os.dispatcher.dispatchEvent(new goog.events.Event(plugin.file.kml.KMLNodeLayerUICtrl.UIEventType.REFRESH)); + os.dispatcher.dispatchEvent(new goog.events.Event(os.action.EventType.REFRESH)); var feature = /** @type {ol.Feature} */ (this.getFeature()); var layer = os.MapContainer.getInstance().getLayer(this.layerId); goog.asserts.assert(layer, 'layer must be defined'); diff --git a/src/plugin/file/kml/kmlnodelayerui.js b/src/plugin/file/kml/kmlnodelayerui.js index 9f9c11b29..a86282372 100644 --- a/src/plugin/file/kml/kmlnodelayerui.js +++ b/src/plugin/file/kml/kmlnodelayerui.js @@ -1,6 +1,7 @@ goog.provide('plugin.file.kml.KMLNodeLayerUICtrl'); -goog.provide('plugin.file.kml.KMLNodeLayerUICtrl.UIEventType'); goog.provide('plugin.file.kml.kmlNodeLayerUIDirective'); + +goog.require('os.action.EventType'); goog.require('os.command.FeatureCenterShape'); goog.require('os.command.FeatureColor'); goog.require('os.command.FeatureIcon'); @@ -102,25 +103,16 @@ plugin.file.kml.KMLNodeLayerUICtrl = function($scope, $element, $timeout) { $scope.$on('fillOpacity.slide', this.onFillOpacityValueChange.bind(this)); $scope.$on('fillOpacity.slidestop', this.onFillOpacityChange.bind(this)); - os.dispatcher.listen(plugin.file.kml.KMLNodeLayerUICtrl.UIEventType.REFRESH, this.initUI, false, this); + os.dispatcher.listen(os.action.EventType.REFRESH, this.initUI, false, this); }; goog.inherits(plugin.file.kml.KMLNodeLayerUICtrl, os.ui.layer.VectorLayerUICtrl); -/** - * UI event types - * @enum {string} - */ -plugin.file.kml.KMLNodeLayerUICtrl.UIEventType = { - REFRESH: 'refresh' -}; - - /** * @inheritDoc */ plugin.file.kml.KMLNodeLayerUICtrl.prototype.disposeInternal = function() { - os.dispatcher.unlisten(os.ui.events.UIEventType.TOGGLE_UI, this.initUI, false, this); + os.dispatcher.unlisten(os.action.EventType.REFRESH, this.initUI, false, this); plugin.file.kml.KMLNodeLayerUICtrl.base(this, 'disposeInternal'); }; @@ -139,12 +131,14 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.getProperties = function() { plugin.file.kml.KMLNodeLayerUICtrl.prototype.initUI = function() { plugin.file.kml.KMLNodeLayerUICtrl.base(this, 'initUI'); - if (this.scope && this.isFeatureFillable()) { - this.scope['fillColor'] = this.getFillColor(); - this.scope['fillOpacity'] = this.getFillOpacity(); - } else { - delete this.scope['fillColor']; - delete this.scope['fillOpacity']; + if (this.scope) { + if (this.isFeatureFillable()) { + this.scope['fillColor'] = this.getFillColor(); + this.scope['fillOpacity'] = this.getFillOpacity(); + } else { + delete this.scope['fillColor']; + delete this.scope['fillOpacity']; + } } }; diff --git a/src/plugin/file/kml/ui/kmlui.js b/src/plugin/file/kml/ui/kmlui.js index 3e46383ef..61dae9ad2 100644 --- a/src/plugin/file/kml/ui/kmlui.js +++ b/src/plugin/file/kml/ui/kmlui.js @@ -2,11 +2,11 @@ goog.provide('plugin.file.kml.ui'); goog.require('goog.asserts'); goog.require('goog.events.Event'); +goog.require('os.action.EventType'); goog.require('os.command.SequenceCommand'); goog.require('os.object'); goog.require('os.style'); goog.require('plugin.file.kml.KMLField'); -goog.require('plugin.file.kml.KMLNodeLayerUICtrl.UIEventType'); goog.require('plugin.file.kml.cmd.KMLNodeAdd'); goog.require('plugin.file.kml.cmd.KMLNodeRemove'); goog.require('plugin.file.kml.kmlNodeLayerUIDirective'); @@ -169,7 +169,7 @@ plugin.file.kml.ui.updatePlacemark = function(options) { placemark.setLabel(feature.get(plugin.file.kml.KMLField.NAME) || 'Unnamed Place'); os.feature.update(feature); feature.changed(); - os.dispatcher.dispatchEvent(new goog.events.Event(plugin.file.kml.KMLNodeLayerUICtrl.UIEventType.REFRESH)); + os.dispatcher.dispatchEvent(new goog.events.Event(os.action.EventType.REFRESH)); } // add the placemark to a parent if provided From cc8e20dfb5e46e0c5f7af25820ef700aaf19ef63 Mon Sep 17 00:00:00 2001 From: Kevin Schmidt Date: Tue, 13 Aug 2019 08:58:14 -0600 Subject: [PATCH 10/28] test(feature): add tests for os.feature.getColor --- src/os/style/style.js | 7 ++-- test/os/feature/feature.test.js | 65 +++++++++++++++++++++++++++++++++ test/os/style/style.test.js | 4 +- 3 files changed, 71 insertions(+), 5 deletions(-) diff --git a/src/os/style/style.js b/src/os/style/style.js index f3a745264..af0af1031 100644 --- a/src/os/style/style.js +++ b/src/os/style/style.js @@ -564,8 +564,8 @@ os.style.STYLE_COLOR_FIELDS_ = ['image', 'fill', 'stroke']; * @param {Object} config The configuration to search for a color * @param {boolean=} opt_array If the color should be returned as an rgb array * @param {os.style.StyleField=} opt_colorField The style field to use in locating the color. - * @return {Array|string|undefined} The color, or undefined if not found. Returns `null` if a style field was - * provided and the field was `null`. + * @return {Array|string|undefined} The color, or null if not found. Returns `undefined` if a style field was + * provided and the field was not present. */ os.style.getConfigColor = function(config, opt_array, opt_colorField) { if (config) { @@ -586,6 +586,7 @@ os.style.getConfigColor = function(config, opt_array, opt_colorField) { return opt_array ? os.color.toRgbArray(config[opt_colorField][os.style.StyleField.COLOR]) : config[opt_colorField][os.style.StyleField.COLOR]; } + return undefined; } else if (config[os.style.StyleField.COLOR] != null) { return opt_array ? os.color.toRgbArray(config[os.style.StyleField.COLOR]) : config[os.style.StyleField.COLOR]; @@ -603,7 +604,7 @@ os.style.getConfigColor = function(config, opt_array, opt_colorField) { } } - return undefined; + return null; }; diff --git a/test/os/feature/feature.test.js b/test/os/feature/feature.test.js index 4f3a52a41..84ffa8019 100644 --- a/test/os/feature/feature.test.js +++ b/test/os/feature/feature.test.js @@ -393,7 +393,72 @@ describe('os.feature', function() { }); it('should get a color from a feature', function() { + var feature = new ol.Feature(); + var testColor = 'rgba(12,34,56,.1)'; + var sourceColor = 'rgba(98,76,54,.2)'; + var featureConfig1 = {}; + var featureConfig2 = { + color: testColor + }; + var source = { + getColor: function() { + return sourceColor; + } + }; + var getSourceSpy = spyOn(os.feature, 'getSource').andReturn(null); + + // should return the app default color when no feature provided + expect(os.feature.getColor(null)).toBe(os.style.DEFAULT_LAYER_COLOR); + // or when a feature provided + expect(os.feature.getColor(feature)).toBe(os.style.DEFAULT_LAYER_COLOR); + // unless a specific default color was specified + expect(os.feature.getColor(feature, undefined, testColor)).toBe(testColor); + // or a source was provided + expect(os.feature.getColor(feature, source)).toBe(sourceColor); + // or a source was available on the feature + getSourceSpy.andReturn(source); + expect(os.feature.getColor(feature)).toBe(sourceColor); + getSourceSpy.andReturn(null); + + // uses feature base color override + feature.set(os.data.RecordField.COLOR, testColor); + expect(os.feature.getColor(feature)).toBe(testColor); + feature.unset(os.data.RecordField.COLOR); + + // empty config returns default color + feature.set(os.style.StyleType.FEATURE, featureConfig1); + expect(os.feature.getColor(feature)).toBe(os.style.DEFAULT_LAYER_COLOR); + + // should return the base config color + featureConfig1.color = testColor; + expect(os.feature.getColor(feature)).toBe(testColor); + delete featureConfig1.color; + + // should return the fill color + featureConfig1.fill = { + color: testColor + }; + expect(os.feature.getColor(feature)).toBe(testColor); + delete featureConfig1.fill; + + // should return the image color + featureConfig1.image = { + color: testColor + }; + expect(os.feature.getColor(feature)).toBe(testColor); + delete featureConfig1.image; + + // should return the stroke color + featureConfig1.stroke = { + color: testColor, + width: 2 + }; + expect(os.feature.getColor(feature)).toBe(testColor); + delete featureConfig1.stroke; + // should find a color in other configs + feature.set(os.style.StyleType.FEATURE, [featureConfig1, featureConfig2]); + expect(os.feature.getColor(feature)).toBe(testColor); }); it('should get a fill color from a feature', function() { diff --git a/test/os/style/style.test.js b/test/os/style/style.test.js index a66e022e4..54dd73436 100644 --- a/test/os/style/style.test.js +++ b/test/os/style/style.test.js @@ -120,8 +120,8 @@ describe('os.style', function() { }; it('should get the color from a config using default fields', function() { - expect(os.style.getConfigColor(null)).toBeUndefined(); - expect(os.style.getConfigColor({})).toBeUndefined(); + expect(os.style.getConfigColor(null)).toBeNull(); + expect(os.style.getConfigColor({})).toBeNull(); expect(os.style.getConfigColor(colorConfig)).toBe(testColor); expect(os.style.getConfigColor(fillConfig)).toBe(testColor); From d0e9016c3ec3fb9dca06be13a16b8f97e29b9898 Mon Sep 17 00:00:00 2001 From: Kevin Wilson Date: Wed, 14 Aug 2019 16:01:22 -0600 Subject: [PATCH 11/28] fix(fillstyle): improvements from code review Combine color-change commands for Layers, fix errors when resetting colors, fix a bug when undoing a fill color change where opacity was set to 1. NOTE: combining color-change commands for Features is currently broken and being investigated. BREAKING CHANGE: Changing stroke+fill colors for Features does not work --- src/os/command/feature/featurecolorcmd.js | 4 +- src/os/command/vectorlayercolorcmd.js | 4 +- src/os/ui/layer/vectorlayerui.js | 49 +++++++------ .../featureaction/featurestyleaction.js | 3 +- .../ui/featurestyleactionconfig.js | 15 ++-- src/plugin/file/kml/kmlnodelayerui.js | 72 ++++++++++++++----- 6 files changed, 101 insertions(+), 46 deletions(-) diff --git a/src/os/command/feature/featurecolorcmd.js b/src/os/command/feature/featurecolorcmd.js index bbcbf1e8e..99bf5323c 100644 --- a/src/os/command/feature/featurecolorcmd.js +++ b/src/os/command/feature/featurecolorcmd.js @@ -18,8 +18,6 @@ goog.require('os.metrics'); * @constructor */ os.command.FeatureColor = function(layerId, featureId, color, opt_oldColor, opt_changeMode) { - os.command.FeatureColor.base(this, 'constructor', layerId, featureId, color, opt_oldColor); - this.changeMode = opt_changeMode; switch (this.changeMode) { @@ -41,6 +39,8 @@ os.command.FeatureColor = function(layerId, featureId, color, opt_oldColor, opt_ break; } + os.command.FeatureColor.base(this, 'constructor', layerId, featureId, color, opt_oldColor); + if (!color) { var feature = /** @type {ol.Feature} */ (this.getFeature()); var config = /** @type {Object|undefined} */ (feature.get(os.style.StyleType.FEATURE)); diff --git a/src/os/command/vectorlayercolorcmd.js b/src/os/command/vectorlayercolorcmd.js index 107fd451e..5f7e7ca5f 100644 --- a/src/os/command/vectorlayercolorcmd.js +++ b/src/os/command/vectorlayercolorcmd.js @@ -20,8 +20,6 @@ goog.require('os.ui'); * @constructor */ os.command.VectorLayerColor = function(layerId, color, opt_oldColor, opt_changeMode) { - os.command.VectorLayerColor.base(this, 'constructor', layerId, color, opt_oldColor); - this.changeMode = opt_changeMode; switch (this.changeMode) { @@ -43,6 +41,8 @@ os.command.VectorLayerColor = function(layerId, color, opt_oldColor, opt_changeM break; } + os.command.VectorLayerColor.base(this, 'constructor', layerId, color, opt_oldColor); + if (!color) { var layer = /** @type {os.layer.Vector} */ (os.MapContainer.getInstance().getLayer(this.layerId)); if (layer) { diff --git a/src/os/ui/layer/vectorlayerui.js b/src/os/ui/layer/vectorlayerui.js index 2e71a3c80..d9174c13e 100644 --- a/src/os/ui/layer/vectorlayerui.js +++ b/src/os/ui/layer/vectorlayerui.js @@ -5,6 +5,7 @@ goog.require('goog.color'); goog.require('os.MapChange'); goog.require('os.array'); goog.require('os.command.LayerStyle'); +goog.require('os.command.SequenceCommand'); goog.require('os.command.VectorLayerAutoRefresh'); goog.require('os.command.VectorLayerCenterShape'); goog.require('os.command.VectorLayerColor'); @@ -327,6 +328,9 @@ os.ui.layer.VectorLayerUICtrl.prototype.reconcileLabelsState_ = function() { * @protected */ os.ui.layer.VectorLayerUICtrl.prototype.onColorChange = function(event, value) { + if (!os.color.isColorString(value) && !goog.isArray(value)) { + return; + } event.stopPropagation(); // Make sure the value includes the current opacity @@ -354,35 +358,37 @@ os.ui.layer.VectorLayerUICtrl.prototype.onColorChange = function(event, value) { this.createCommand(fn); } else if (color == fillColor) { - // We run these separately so that they retain the different opacities + var strokeArray = colorValue.slice(0, 3); + strokeArray.push(opacity); + var fillArray = colorValue.slice(0, 3); + fillArray.push(fillOpacity); + + // We run these sequentially so that they retain the different opacities var fn2 = /** * @param {os.layer.ILayer} layer * @return {os.command.ICommand} */ function(layer) { - return new os.command.VectorLayerColor( - layer.getId(), colorValue, null, os.command.VectorLayerColor.MODE.STROKE); - }; + var cmds = []; - this.createCommand(fn2); + cmds.push(new os.command.VectorLayerColor( + layer.getId(), strokeArray, null, os.command.VectorLayerColor.MODE.STROKE) + ); + cmds.push(new os.command.VectorLayerColor( + layer.getId(), fillArray, null, os.command.VectorLayerColor.MODE.FILL) + ); - // Use the fill's opacity instead of the stroke's opacity - colorValue[3] = fillOpacity; + var sequence = new os.command.SequenceCommand(); + sequence.setCommands(cmds); + sequence.title = 'Change Color'; - var fn3 = - /** - * @param {os.layer.ILayer} layer - * @return {os.command.ICommand} - */ - function(layer) { - return new os.command.VectorLayerColor( - layer.getId(), colorValue, null, os.command.VectorLayerColor.MODE.FILL); + return sequence; }; - this.createCommand(fn3); + this.createCommand(fn2); } else { - var fn4 = + var fn3 = /** * @param {os.layer.ILayer} layer * @return {os.command.ICommand} @@ -392,7 +398,7 @@ os.ui.layer.VectorLayerUICtrl.prototype.onColorChange = function(event, value) { layer.getId(), colorValue, null, os.command.VectorLayerColor.MODE.STROKE); }; - this.createCommand(fn4); + this.createCommand(fn3); } }; @@ -406,7 +412,7 @@ os.ui.layer.VectorLayerUICtrl.prototype.onColorReset = function(event) { event.stopPropagation(); // clear the layer color config value - this.onColorChange(event, ''); + this.onColorChange(event, os.style.DEFAULT_LAYER_COLOR); // reset to the layer color this.scope['color'] = this.getColor(); @@ -420,6 +426,9 @@ os.ui.layer.VectorLayerUICtrl.prototype.onColorReset = function(event) { * @protected */ os.ui.layer.VectorLayerUICtrl.prototype.onFillColorChange = function(event, value) { + if (!os.color.isColorString(value) && !goog.isArray(value)) { + return; + } event.stopPropagation(); // Make sure the value includes the current opacity @@ -451,7 +460,7 @@ os.ui.layer.VectorLayerUICtrl.prototype.onFillColorReset = function(event) { event.stopPropagation(); // clear the layer color config value - this.onFillColorChange(event, ''); + this.onFillColorChange(event, os.style.DEFAULT_FILL_COLOR); // reset to the layer color this.scope['fillColor'] = this.getColor(); diff --git a/src/plugin/featureaction/featurestyleaction.js b/src/plugin/featureaction/featurestyleaction.js index 74b03776f..376e77b3d 100644 --- a/src/plugin/featureaction/featurestyleaction.js +++ b/src/plugin/featureaction/featurestyleaction.js @@ -306,7 +306,8 @@ plugin.im.action.feature.StyleAction.prototype.fromXml = function(xml) { fillColor = os.style.toRgbaString(fillColorArr); } - os.style.setConfigColor(styleConfig, fillColor, [os.style.StyleField.FILL]); + // Only change the fill color without changing the image fill color too + styleConfig.fill.color = fillColor; } var size = parseFloat(os.xml.getChildValue(xml, plugin.im.action.feature.StyleActionTagName.SIZE)); diff --git a/src/plugin/featureaction/ui/featurestyleactionconfig.js b/src/plugin/featureaction/ui/featurestyleactionconfig.js index 210db3f57..07198ed75 100644 --- a/src/plugin/featureaction/ui/featurestyleactionconfig.js +++ b/src/plugin/featureaction/ui/featurestyleactionconfig.js @@ -154,9 +154,9 @@ plugin.im.action.feature.ui.StyleConfigCtrl.prototype.initialize = function() { var strokeColor = os.style.toRgbaString(color); os.style.setConfigColor(this.styleConfig, strokeColor); - // If we have a fill color, standardize that too + // If we have a fill color, set that to our style config var fillColor = os.style.toRgbaString(fill); - os.style.setConfigColor(this.styleConfig, fillColor, [os.style.StyleField.FILL]); + this.styleConfig.fill.color = fillColor; this.scope['size'] = os.style.getConfigSize(this.styleConfig); this.scope['lineDash'] = os.style.getConfigLineDash(this.styleConfig); @@ -252,7 +252,9 @@ plugin.im.action.feature.ui.StyleConfigCtrl.prototype.onColorChange = function(e os.style.setConfigColor(this.styleConfig, color); this.scope['color'] = os.color.toHexString(color); - os.style.setConfigColor(this.styleConfig, fillColor, [os.style.StyleField.FILL]); + // Only change the fill color without changing the image fill color too + this.styleConfig.fill.color = fillColor; + this.scope['fillColor'] = os.color.toHexString(fillColor); } else { // change just the stroke color @@ -286,7 +288,8 @@ plugin.im.action.feature.ui.StyleConfigCtrl.prototype.onFillColorChange = functi color = os.style.toRgbaString(colorArr); } - os.style.setConfigColor(this.styleConfig, color, [os.style.StyleField.FILL]); + // Only change the fill color without changing the image fill color too + this.styleConfig.fill.color = color; this.scope['fillColor'] = os.color.toHexString(color); } @@ -360,7 +363,9 @@ plugin.im.action.feature.ui.StyleConfigCtrl.prototype.onOpacityChange = function if (event.name == 'fillOpacity.slidestop') { color = os.style.getConfigColor(this.styleConfig, true, os.style.StyleField.FILL); color[3] = value; - os.style.setConfigColor(this.styleConfig, color, [os.style.StyleField.FILL]); + + // Only change the fill color without changing the image fill color too + this.styleConfig.fill.color = color; this.scope['fillOpacity'] = value; } else { diff --git a/src/plugin/file/kml/kmlnodelayerui.js b/src/plugin/file/kml/kmlnodelayerui.js index a86282372..5d29aa4c6 100644 --- a/src/plugin/file/kml/kmlnodelayerui.js +++ b/src/plugin/file/kml/kmlnodelayerui.js @@ -14,6 +14,7 @@ goog.require('os.command.FeatureShape'); goog.require('os.command.FeatureShowLabel'); goog.require('os.command.FeatureSize'); goog.require('os.command.ParallelCommand'); +goog.require('os.command.SequenceCommand'); goog.require('os.data.ColumnDefinition'); goog.require('os.geo'); goog.require('os.ui.Module'); @@ -576,6 +577,9 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onLockChange = function() { * @inheritDoc */ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onColorChange = function(event, value) { + if (!os.color.isColorString(value) && !goog.isArray(value)) { + return; + } event.stopPropagation(); // Make sure the value includes the current opacity @@ -617,26 +621,19 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onColorChange = function(event, val * @return {os.command.ICommand} */ function(layerId, featureId) { - return new os.command.FeatureColor(layerId, featureId, colorValue, null, os.command.FeatureColor.MODE.STROKE); - }; + var cmds = []; - this.createFeatureCommand(fn2); - - // Use the fill's opacity instead of the stroke's opacity - colorValue[3] = this.scope['fillOpacity']; - this.scope['fillColor'] = os.style.toRgbaString(colorValue); + cmds.push(new os.command.FeatureColor( + layerId, featureId, strokeColorArr, null, os.command.FeatureColor.MODE.STROKE) + ); + cmds.push(new os.command.FeatureColor( + layerId, featureId, fillColorArr, null, os.command.FeatureColor.MODE.FILL) + ); - var fn3 = - /** - * @param {string} layerId - * @param {string} featureId - * @return {os.command.ICommand} - */ - function(layerId, featureId) { - return new os.command.FeatureColor(layerId, featureId, colorValue, null, os.command.FeatureColor.MODE.FILL); + return cmds; }; - this.createFeatureCommand(fn3); + this.createFeatureSequenceCommand(fn2, 'Change Feature Color'); } else { var fn4 = /** @@ -671,6 +668,9 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onColorChange = function(event, val * @inheritDoc */ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onFillColorChange = function(event, value) { + if (!os.color.isColorString(value) && !goog.isArray(value)) { + return; + } event.stopPropagation(); // Make sure the value includes the current opacity @@ -1092,6 +1092,46 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.createFeatureCommand = function(com }; +/** + * Creates a sequence of commands to run on each feature + * + * @param {function(string, string):os.command.ICommand} commandFunction + * @param {string=} title + */ +plugin.file.kml.KMLNodeLayerUICtrl.prototype.createFeatureSequenceCommand = function(commandFunction, title) { + var cmds = []; + + var items = /** @type {Array} */ (this.scope['items']); + if (items) { + for (var i = 0; i < items.length; i++) { + var feature = items[i].getFeature(); + var source = items[i].getSource(); + if (feature && source) { + var featureId = feature.getId(); + var layerId = source.getId(); + if (featureId && layerId) { + if (typeof featureId == 'number') { + featureId = featureId.toString(); + } + + var result = commandFunction(layerId, featureId); + if (result.length > 0) { + cmds = cmds.concat(result); + } + } + } + } + } + + if (cmds.length > 0) { + var sequence = new os.command.SequenceCommand(); + sequence.setCommands(cmds); + sequence.title = title ? title : ''; + + os.command.CommandProcessor.getInstance().addCommand(sequence); + } +}; + /** * If the feature is dynamic, which means it is a time based track * From 55bf63af62d450dcaee75e127fd2aae238953ddf Mon Sep 17 00:00:00 2001 From: Kevin Wilson Date: Thu, 15 Aug 2019 09:57:09 -0600 Subject: [PATCH 12/28] fix(fillstyle): code review, combine Feature command calls --- src/os/command/feature/featurecolorcmd.js | 4 +- src/os/command/vectorlayercolorcmd.js | 4 +- src/os/ui/layer/vectorlayerui.js | 4 +- .../featureaction/featurestyleaction.js | 2 +- .../ui/featurestyleactionconfig.js | 2 +- src/plugin/file/kml/kmlnodelayerui.js | 59 ++++--------------- 6 files changed, 18 insertions(+), 57 deletions(-) diff --git a/src/os/command/feature/featurecolorcmd.js b/src/os/command/feature/featurecolorcmd.js index 99bf5323c..cedc50ec7 100644 --- a/src/os/command/feature/featurecolorcmd.js +++ b/src/os/command/feature/featurecolorcmd.js @@ -20,6 +20,8 @@ goog.require('os.metrics'); os.command.FeatureColor = function(layerId, featureId, color, opt_oldColor, opt_changeMode) { this.changeMode = opt_changeMode; + os.command.FeatureColor.base(this, 'constructor', layerId, featureId, color, opt_oldColor); + switch (this.changeMode) { case os.command.FeatureColor.MODE.FILL: this.title = 'Change Feature Fill Color'; @@ -39,8 +41,6 @@ os.command.FeatureColor = function(layerId, featureId, color, opt_oldColor, opt_ break; } - os.command.FeatureColor.base(this, 'constructor', layerId, featureId, color, opt_oldColor); - if (!color) { var feature = /** @type {ol.Feature} */ (this.getFeature()); var config = /** @type {Object|undefined} */ (feature.get(os.style.StyleType.FEATURE)); diff --git a/src/os/command/vectorlayercolorcmd.js b/src/os/command/vectorlayercolorcmd.js index 5f7e7ca5f..ba17a427f 100644 --- a/src/os/command/vectorlayercolorcmd.js +++ b/src/os/command/vectorlayercolorcmd.js @@ -22,6 +22,8 @@ goog.require('os.ui'); os.command.VectorLayerColor = function(layerId, color, opt_oldColor, opt_changeMode) { this.changeMode = opt_changeMode; + os.command.VectorLayerColor.base(this, 'constructor', layerId, color, opt_oldColor); + switch (this.changeMode) { case os.command.VectorLayerColor.MODE.FILL: this.title = 'Change Fill Color'; @@ -41,8 +43,6 @@ os.command.VectorLayerColor = function(layerId, color, opt_oldColor, opt_changeM break; } - os.command.VectorLayerColor.base(this, 'constructor', layerId, color, opt_oldColor); - if (!color) { var layer = /** @type {os.layer.Vector} */ (os.MapContainer.getInstance().getLayer(this.layerId)); if (layer) { diff --git a/src/os/ui/layer/vectorlayerui.js b/src/os/ui/layer/vectorlayerui.js index d9174c13e..a07726198 100644 --- a/src/os/ui/layer/vectorlayerui.js +++ b/src/os/ui/layer/vectorlayerui.js @@ -460,10 +460,10 @@ os.ui.layer.VectorLayerUICtrl.prototype.onFillColorReset = function(event) { event.stopPropagation(); // clear the layer color config value - this.onFillColorChange(event, os.style.DEFAULT_FILL_COLOR); + this.onFillColorChange(event, this.getColor()); // reset to the layer color - this.scope['fillColor'] = this.getColor(); + this.scope['fillColor'] = this.getFillColor(); }; diff --git a/src/plugin/featureaction/featurestyleaction.js b/src/plugin/featureaction/featurestyleaction.js index 376e77b3d..0af0cc779 100644 --- a/src/plugin/featureaction/featurestyleaction.js +++ b/src/plugin/featureaction/featurestyleaction.js @@ -307,7 +307,7 @@ plugin.im.action.feature.StyleAction.prototype.fromXml = function(xml) { } // Only change the fill color without changing the image fill color too - styleConfig.fill.color = fillColor; + styleConfig['fill']['color'] = fillColor; } var size = parseFloat(os.xml.getChildValue(xml, plugin.im.action.feature.StyleActionTagName.SIZE)); diff --git a/src/plugin/featureaction/ui/featurestyleactionconfig.js b/src/plugin/featureaction/ui/featurestyleactionconfig.js index 07198ed75..8c777b5da 100644 --- a/src/plugin/featureaction/ui/featurestyleactionconfig.js +++ b/src/plugin/featureaction/ui/featurestyleactionconfig.js @@ -289,7 +289,7 @@ plugin.im.action.feature.ui.StyleConfigCtrl.prototype.onFillColorChange = functi } // Only change the fill color without changing the image fill color too - this.styleConfig.fill.color = color; + this.styleConfig['fill']['color'] = color; this.scope['fillColor'] = os.color.toHexString(color); } diff --git a/src/plugin/file/kml/kmlnodelayerui.js b/src/plugin/file/kml/kmlnodelayerui.js index 5d29aa4c6..1c3bfb163 100644 --- a/src/plugin/file/kml/kmlnodelayerui.js +++ b/src/plugin/file/kml/kmlnodelayerui.js @@ -613,7 +613,7 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onColorChange = function(event, val this.createFeatureCommand(fn); } else if (color == fillColor) { - // We run these separately so that they retain the different opacities + // We create two commands so that they retain the different opacities var fn2 = /** * @param {string} layerId @@ -630,10 +630,14 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onColorChange = function(event, val layerId, featureId, fillColorArr, null, os.command.FeatureColor.MODE.FILL) ); - return cmds; + var sequence = new os.command.SequenceCommand(); + sequence.setCommands(cmds); + sequence.title = 'Change Color'; + + return sequence; }; - this.createFeatureSequenceCommand(fn2, 'Change Feature Color'); + this.createFeatureCommand(fn2); } else { var fn4 = /** @@ -1062,12 +1066,9 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.createFeatureCommand = function(com var feature = items[i].getFeature(); var source = items[i].getSource(); if (feature && source) { - var featureId = feature.getId(); - var layerId = source.getId(); - if (featureId && layerId) { - if (typeof featureId == 'number') { - featureId = featureId.toString(); - } + var featureId = String(feature.getId()); + var layerId = String(source.getId()); + if (featureId != null && layerId != null) { var cmd = commandFunction(layerId, featureId); if (cmd) { // if we have a feature and get a command, add it cmds.push(cmd); @@ -1092,46 +1093,6 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.createFeatureCommand = function(com }; -/** - * Creates a sequence of commands to run on each feature - * - * @param {function(string, string):os.command.ICommand} commandFunction - * @param {string=} title - */ -plugin.file.kml.KMLNodeLayerUICtrl.prototype.createFeatureSequenceCommand = function(commandFunction, title) { - var cmds = []; - - var items = /** @type {Array} */ (this.scope['items']); - if (items) { - for (var i = 0; i < items.length; i++) { - var feature = items[i].getFeature(); - var source = items[i].getSource(); - if (feature && source) { - var featureId = feature.getId(); - var layerId = source.getId(); - if (featureId && layerId) { - if (typeof featureId == 'number') { - featureId = featureId.toString(); - } - - var result = commandFunction(layerId, featureId); - if (result.length > 0) { - cmds = cmds.concat(result); - } - } - } - } - } - - if (cmds.length > 0) { - var sequence = new os.command.SequenceCommand(); - sequence.setCommands(cmds); - sequence.title = title ? title : ''; - - os.command.CommandProcessor.getInstance().addCommand(sequence); - } -}; - /** * If the feature is dynamic, which means it is a time based track * From d65709f6f5ce54ee9eed05dde9ae4b0d5ff44e30 Mon Sep 17 00:00:00 2001 From: Kevin Wilson Date: Thu, 15 Aug 2019 10:17:16 -0600 Subject: [PATCH 13/28] fix(fillstyle): lint/compile fixes --- src/os/ui/layer/vectorlayerui.js | 2 +- src/plugin/file/kml/kmlnodelayerui.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/os/ui/layer/vectorlayerui.js b/src/os/ui/layer/vectorlayerui.js index a07726198..015354ec8 100644 --- a/src/os/ui/layer/vectorlayerui.js +++ b/src/os/ui/layer/vectorlayerui.js @@ -460,7 +460,7 @@ os.ui.layer.VectorLayerUICtrl.prototype.onFillColorReset = function(event) { event.stopPropagation(); // clear the layer color config value - this.onFillColorChange(event, this.getColor()); + this.onFillColorChange(event, os.style.toRgbaString(this.getColor())); // reset to the layer color this.scope['fillColor'] = this.getFillColor(); diff --git a/src/plugin/file/kml/kmlnodelayerui.js b/src/plugin/file/kml/kmlnodelayerui.js index 1c3bfb163..dddf15cf2 100644 --- a/src/plugin/file/kml/kmlnodelayerui.js +++ b/src/plugin/file/kml/kmlnodelayerui.js @@ -624,10 +624,10 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onColorChange = function(event, val var cmds = []; cmds.push(new os.command.FeatureColor( - layerId, featureId, strokeColorArr, null, os.command.FeatureColor.MODE.STROKE) + layerId, featureId, strokeColorArr, null, os.command.FeatureColor.MODE.STROKE) ); cmds.push(new os.command.FeatureColor( - layerId, featureId, fillColorArr, null, os.command.FeatureColor.MODE.FILL) + layerId, featureId, fillColorArr, null, os.command.FeatureColor.MODE.FILL) ); var sequence = new os.command.SequenceCommand(); From de6e81cbf16c4c155e957fe574925a3bfb2bfbc5 Mon Sep 17 00:00:00 2001 From: Kevin Wilson Date: Fri, 16 Aug 2019 11:10:46 -0600 Subject: [PATCH 14/28] fix(fillstyle): fix upgrade, undo, and reset issues --- src/os/layer/vector.js | 14 ++++++--- src/os/ui/layer/vectorlayerui.js | 4 ++- src/plugin/file/kml/kmlnodelayerui.js | 41 ++++++++++++++------------- 3 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/os/layer/vector.js b/src/os/layer/vector.js index b4bc37a9e..2da9e810e 100644 --- a/src/os/layer/vector.js +++ b/src/os/layer/vector.js @@ -1242,11 +1242,17 @@ os.layer.Vector.prototype.restore = function(config) { if (config[os.style.StyleField.COLOR] != null) { os.style.setConfigColor(styleConf, os.style.toRgbaString(config[os.style.StyleField.COLOR])); - } - if (config[os.style.StyleField.FILL_COLOR] != null) { - var fillString = os.style.toRgbaString(config[os.style.StyleField.FILL_COLOR]); - os.style.setConfigColor(styleConf, fillString, [os.style.StyleField.FILL]); + if (config[os.style.StyleField.FILL_COLOR] != null) { + var fillString = os.style.toRgbaString(config[os.style.StyleField.FILL_COLOR]); + os.style.setConfigColor(styleConf, fillString, [os.style.StyleField.FILL]); + } else { + var fillArr = os.color.toRgbArray(config[os.style.StyleField.COLOR]); + fillArr[3] = os.style.DEFAULT_FILL_ALPHA; + styleConf['fill'] = { + 'color': os.style.toRgbaString(fillArr) + }; + } } if (config[os.style.StyleField.REPLACE_STYLE] != null) { diff --git a/src/os/ui/layer/vectorlayerui.js b/src/os/ui/layer/vectorlayerui.js index 015354ec8..294d7c65d 100644 --- a/src/os/ui/layer/vectorlayerui.js +++ b/src/os/ui/layer/vectorlayerui.js @@ -883,7 +883,9 @@ os.ui.layer.VectorLayerUICtrl.prototype.getFillOpacity = function() { config = config[0]; } var color = os.style.getConfigColor(config, true, os.style.StyleField.FILL); - opacity = color[3]; + if (goog.isArray(color) && color.length >= 4) { + opacity = color[3]; + } } } } diff --git a/src/plugin/file/kml/kmlnodelayerui.js b/src/plugin/file/kml/kmlnodelayerui.js index dddf15cf2..81924b728 100644 --- a/src/plugin/file/kml/kmlnodelayerui.js +++ b/src/plugin/file/kml/kmlnodelayerui.js @@ -589,18 +589,10 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onColorChange = function(event, val // Do we have fill color/opacity to consider? if (this.scope['fillColor'] !== undefined && this.scope['fillOpacity'] !== undefined) { // Determine if we are changing both stroke and fill entirely, or keeping opacities separate, or only affecting stroke - var strokeColorArr = os.color.toRgbArray(this.scope['color']); - strokeColorArr[3] = this.scope['opacity']; - var strokeColorValue = os.style.toRgbaString(strokeColorArr); - var fillColorArr = os.color.toRgbArray(this.scope['fillColor']); - fillColorArr[3] = this.scope['fillOpacity']; - var fillColorValue = os.style.toRgbaString(fillColorArr); - var color = os.color.toHexString(this.scope['color']); - var fillColor = os.color.toHexString(this.scope['fillColor']); - - this.scope['color'] = os.color.toHexString(colorValue); - - if (strokeColorValue == fillColorValue) { + if (this.scope['color'] == this.scope['fillColor'] && this.scope['opacity'] == this.scope['fillOpacity']) { + this.scope['color'] = os.color.toHexString(colorValue); + this.scope['fillColor'] = os.color.toHexString(colorValue); + var fn = /** * @param {string} layerId @@ -612,8 +604,16 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onColorChange = function(event, val }; this.createFeatureCommand(fn); - } else if (color == fillColor) { + } else if (this.scope['color'] == this.scope['fillColor']) { + this.scope['color'] = os.color.toHexString(colorValue); + this.scope['fillColor'] = os.color.toHexString(colorValue); + // We create two commands so that they retain the different opacities + var strokeColor = os.color.toRgbArray(this.scope['color']); + strokeColor[3] = this.scope['opacity']; + var fillColor = os.color.toRgbArray(this.scope['fillColor']); + fillColor[3] = this.scope['fillOpacity']; + var fn2 = /** * @param {string} layerId @@ -624,10 +624,10 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onColorChange = function(event, val var cmds = []; cmds.push(new os.command.FeatureColor( - layerId, featureId, strokeColorArr, null, os.command.FeatureColor.MODE.STROKE) + layerId, featureId, strokeColor, null, os.command.FeatureColor.MODE.STROKE) ); cmds.push(new os.command.FeatureColor( - layerId, featureId, fillColorArr, null, os.command.FeatureColor.MODE.FILL) + layerId, featureId, fillColor, null, os.command.FeatureColor.MODE.FILL) ); var sequence = new os.command.SequenceCommand(); @@ -639,7 +639,8 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onColorChange = function(event, val this.createFeatureCommand(fn2); } else { - var fn4 = + this.scope['color'] = os.color.toHexString(colorValue); + var fn3 = /** * @param {string} layerId * @param {string} featureId @@ -649,7 +650,7 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onColorChange = function(event, val return new os.command.FeatureColor(layerId, featureId, colorValue, null, os.command.FeatureColor.MODE.STROKE); }; - this.createFeatureCommand(fn4); + this.createFeatureCommand(fn3); } } else { // We are not taking fill into consideration @@ -1066,9 +1067,11 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.createFeatureCommand = function(com var feature = items[i].getFeature(); var source = items[i].getSource(); if (feature && source) { - var featureId = String(feature.getId()); - var layerId = String(source.getId()); + var featureId = feature.getId(); + var layerId = source.getId(); if (featureId != null && layerId != null) { + featureId = String(featureId); + layerId = String(layerId); var cmd = commandFunction(layerId, featureId); if (cmd) { // if we have a feature and get a command, add it cmds.push(cmd); From 9494c1101f570b8b0c356d3acc7f029b7ea8edd8 Mon Sep 17 00:00:00 2001 From: Kevin Wilson Date: Fri, 16 Aug 2019 15:37:57 -0600 Subject: [PATCH 15/28] fix(fillstyle): fix recursion headache with fill color --- src/os/command/feature/featurecolorcmd.js | 10 ++++++-- src/os/command/feature/featureopacitycmd.js | 8 +++++- src/os/command/vectorlayercolorcmd.js | 10 +++++--- src/os/command/vectorlayeropacitycmd.js | 8 ++++-- src/os/layer/vector.js | 6 ++--- src/os/style/style.js | 25 +++++++++++++++++++ src/os/ui/featureedit.js | 2 +- .../featureaction/featurestyleaction.js | 2 +- .../ui/featurestyleactionconfig.js | 9 +++++-- 9 files changed, 64 insertions(+), 16 deletions(-) diff --git a/src/os/command/feature/featurecolorcmd.js b/src/os/command/feature/featurecolorcmd.js index cedc50ec7..de4d48fb3 100644 --- a/src/os/command/feature/featurecolorcmd.js +++ b/src/os/command/feature/featurecolorcmd.js @@ -135,12 +135,18 @@ os.command.FeatureColor.prototype.applyValue = function(configs, value) { switch (this.changeMode) { case os.command.FeatureColor.MODE.FILL: for (var i = 0; i < configs.length; i++) { - os.style.setConfigColor(configs[i], color, [os.style.StyleField.FILL]); + os.style.setFillColor(configs[i], color); } break; case os.command.FeatureColor.MODE.STROKE: for (var i = 0; i < configs.length; i++) { - os.style.setConfigColor(configs[i], color, [os.style.StyleField.STROKE, os.style.StyleField.IMAGE]); + var fillColor = os.style.getConfigColor(configs[i], true, os.style.StyleField.FILL); + + os.style.setConfigColor(configs[i], color); + + if (fillColor) { + os.style.setFillColor(configs[i], fillColor); + } } if (this.oldValue == this.getLabelValue()) { diff --git a/src/os/command/feature/featureopacitycmd.js b/src/os/command/feature/featureopacitycmd.js index ef83b3760..6c369efec 100644 --- a/src/os/command/feature/featureopacitycmd.js +++ b/src/os/command/feature/featureopacitycmd.js @@ -141,7 +141,13 @@ os.command.FeatureOpacity.prototype.applyValue = function(configs, value) { color = os.style.getConfigColor(configs[i], true, os.style.StyleField.STROKE); color[3] = value; colorValue = os.style.toRgbaString(color); - os.style.setConfigColor(configs[i], colorValue, [os.style.StyleField.STROKE, os.style.StyleField.IMAGE]); + var fillColor = os.style.getConfigColor(configs[i], true, os.style.StyleField.FILL); + + os.style.setConfigColor(configs[i], colorValue); + + if (fillColor) { + os.style.setFillColor(configs[i], fillColor); + } } break; case os.command.FeatureOpacity.MODE.COMBINED: diff --git a/src/os/command/vectorlayercolorcmd.js b/src/os/command/vectorlayercolorcmd.js index ba17a427f..e36c194de 100644 --- a/src/os/command/vectorlayercolorcmd.js +++ b/src/os/command/vectorlayercolorcmd.js @@ -113,7 +113,7 @@ os.command.VectorLayerColor.prototype.applyValue = function(config, value) { switch (this.changeMode) { case os.command.VectorLayerColor.MODE.FILL: - os.style.setConfigColor(config, color, [os.style.StyleField.FILL]); + os.style.setFillColor(config, color); // Make sure the fill color and opacity are updated as well if (config['fillColor']) { @@ -121,8 +121,12 @@ os.command.VectorLayerColor.prototype.applyValue = function(config, value) { } break; case os.command.VectorLayerColor.MODE.STROKE: - os.style.setConfigColor(config, color, - [os.style.StyleField.STROKE, os.style.StyleField.IMAGE]); + os.style.setConfigColor(config, color); + + if (config['fillColor']) { + os.style.setFillColor(config, config['fillColor']); + } + os.ui.adjustIconSet(this.layerId, color); break; case os.command.VectorLayerColor.MODE.COMBINED: diff --git a/src/os/command/vectorlayeropacitycmd.js b/src/os/command/vectorlayeropacitycmd.js index 312846c5a..e8f19442e 100644 --- a/src/os/command/vectorlayeropacitycmd.js +++ b/src/os/command/vectorlayeropacitycmd.js @@ -100,7 +100,7 @@ os.command.VectorLayerOpacity.prototype.applyValue = function(config, value) { color[3] = value; colorString = os.style.toRgbaString(color); - os.style.setConfigColor(config, colorString, [os.style.StyleField.FILL]); + os.style.setFillColor(config, colorString); // Make sure the fill color and opacity are updated as well if (config['fillColor']) { @@ -116,7 +116,11 @@ os.command.VectorLayerOpacity.prototype.applyValue = function(config, value) { color[3] = value; colorString = os.style.toRgbaString(color); - os.style.setConfigColor(config, colorString, [os.style.StyleField.IMAGE, os.style.StyleField.STROKE]); + os.style.setConfigColor(config, color); + + if (config['fillColor']) { + os.style.setFillColor(config, config['fillColor']); + } os.ui.adjustIconSet(this.layerId, color); diff --git a/src/os/layer/vector.js b/src/os/layer/vector.js index 2da9e810e..5f5e13221 100644 --- a/src/os/layer/vector.js +++ b/src/os/layer/vector.js @@ -1245,13 +1245,11 @@ os.layer.Vector.prototype.restore = function(config) { if (config[os.style.StyleField.FILL_COLOR] != null) { var fillString = os.style.toRgbaString(config[os.style.StyleField.FILL_COLOR]); - os.style.setConfigColor(styleConf, fillString, [os.style.StyleField.FILL]); + os.style.setFillColor(styleConf, fillString); } else { var fillArr = os.color.toRgbArray(config[os.style.StyleField.COLOR]); fillArr[3] = os.style.DEFAULT_FILL_ALPHA; - styleConf['fill'] = { - 'color': os.style.toRgbaString(fillArr) - }; + os.style.setFillColor(styleConf, os.style.toRgbaString(fillArr)); } } diff --git a/src/os/style/style.js b/src/os/style/style.js index af0af1031..78a348b6d 100644 --- a/src/os/style/style.js +++ b/src/os/style/style.js @@ -638,6 +638,31 @@ os.style.setConfigColor = function(config, color, opt_includeStyleFields) { }; +/** + * Sets the fill color, creating the fill object within the config if necessary. + * Colors are always set as an rgba string to minimize conversion both in opensphere style functions and OL3 rendering functions. + * + * @param {Object} config + * @param {Array|string|null} color + */ +os.style.setFillColor = function(config, color) { + if (config) { + if (!color) { + // no fill + config['fill'] = null; + } else if (!config['fill']) { + // adding fill + config['fill'] = { + 'color': color + }; + } else { + // changing fill color + config['fill']['color'] = color; + } + } +}; + + /** * Gets the icon used in a config. * diff --git a/src/os/ui/featureedit.js b/src/os/ui/featureedit.js index 75e5c1d52..6b70a5e64 100644 --- a/src/os/ui/featureedit.js +++ b/src/os/ui/featureedit.js @@ -1319,7 +1319,7 @@ os.ui.FeatureEditCtrl.prototype.setFeatureConfig_ = function(config) { fillColor = os.style.toRgbaString(fillColor); if (color != fillColor) { - os.style.setConfigColor(config, fillColor, [os.style.StyleField.FILL]); + os.style.setFillColor(config, fillColor); } // set icon config if selected diff --git a/src/plugin/featureaction/featurestyleaction.js b/src/plugin/featureaction/featurestyleaction.js index 0af0cc779..c930f9b0e 100644 --- a/src/plugin/featureaction/featurestyleaction.js +++ b/src/plugin/featureaction/featurestyleaction.js @@ -307,7 +307,7 @@ plugin.im.action.feature.StyleAction.prototype.fromXml = function(xml) { } // Only change the fill color without changing the image fill color too - styleConfig['fill']['color'] = fillColor; + os.style.setFillColor(styleConfig, fillColor); } var size = parseFloat(os.xml.getChildValue(xml, plugin.im.action.feature.StyleActionTagName.SIZE)); diff --git a/src/plugin/featureaction/ui/featurestyleactionconfig.js b/src/plugin/featureaction/ui/featurestyleactionconfig.js index 8c777b5da..32deaa30d 100644 --- a/src/plugin/featureaction/ui/featurestyleactionconfig.js +++ b/src/plugin/featureaction/ui/featurestyleactionconfig.js @@ -289,7 +289,7 @@ plugin.im.action.feature.ui.StyleConfigCtrl.prototype.onFillColorChange = functi } // Only change the fill color without changing the image fill color too - this.styleConfig['fill']['color'] = color; + os.style.setFillColor(this.styleConfig, color); this.scope['fillColor'] = os.color.toHexString(color); } @@ -384,7 +384,12 @@ plugin.im.action.feature.ui.StyleConfigCtrl.prototype.onOpacityChange = function } else { color = os.style.getConfigColor(this.styleConfig, true, os.style.StyleField.STROKE); color[3] = value; - os.style.setConfigColor(this.styleConfig, color, [os.style.StyleField.STROKE, os.style.StyleField.IMAGE]); + + os.style.setConfigColor(this.styleConfig, color); + + if (this.scope['fillColor']) { + os.style.setFillColor(this.styleConfig, this.styleConfig['fillColor']); + } this.scope['opacity'] = value; } From ac95f63a0fbe271f79c52cb62502bd99ebe79644 Mon Sep 17 00:00:00 2001 From: Kevin Schmidt Date: Fri, 16 Aug 2019 17:05:16 -0600 Subject: [PATCH 16/28] refactor(style): remove user-facing references to stroke color/opacity --- src/os/command/feature/featurecolorcmd.js | 4 ++-- src/os/command/feature/featureopacitycmd.js | 4 ++-- src/os/command/vectorlayercolorcmd.js | 4 ++-- src/os/command/vectorlayeropacitycmd.js | 4 ++-- src/os/metrics/layersmetrics.js | 20 -------------------- src/os/metrics/metricskeys.js | 4 ---- 6 files changed, 8 insertions(+), 32 deletions(-) diff --git a/src/os/command/feature/featurecolorcmd.js b/src/os/command/feature/featurecolorcmd.js index de4d48fb3..09e4b8973 100644 --- a/src/os/command/feature/featurecolorcmd.js +++ b/src/os/command/feature/featurecolorcmd.js @@ -29,8 +29,8 @@ os.command.FeatureColor = function(layerId, featureId, color, opt_oldColor, opt_ this.defaultColor = os.command.FeatureColor.DEFAULT_FILL_COLOR; break; case os.command.FeatureColor.MODE.STROKE: - this.title = 'Change Feature Stroke Color'; - this.metricKey = os.metrics.Layer.FEATURE_STROKE_COLOR; + this.title = 'Change Feature Color'; + this.metricKey = os.metrics.Layer.FEATURE_COLOR; this.defaultColor = os.command.FeatureColor.DEFAULT_COLOR; break; case os.command.FeatureColor.MODE.COMBINED: diff --git a/src/os/command/feature/featureopacitycmd.js b/src/os/command/feature/featureopacitycmd.js index 6c369efec..7a2be3084 100644 --- a/src/os/command/feature/featureopacitycmd.js +++ b/src/os/command/feature/featureopacitycmd.js @@ -29,8 +29,8 @@ os.command.FeatureOpacity = function(layerId, featureId, opacity, opt_oldOpacity this.defaultOpacity = os.command.FeatureOpacity.DEFAULT_FILL_OPACITY; break; case os.command.FeatureOpacity.MODE.STROKE: - this.title = 'Change Feature Stroke Opacity'; - this.metricKey = os.metrics.Layer.FEATURE_STROKE_OPACITY; + this.title = 'Change Feature Opacity'; + this.metricKey = os.metrics.Layer.FEATURE_OPACITY; this.defaultOpacity = os.command.FeatureOpacity.DEFAULT_OPACITY; break; case os.command.FeatureOpacity.MODE.COMBINED: diff --git a/src/os/command/vectorlayercolorcmd.js b/src/os/command/vectorlayercolorcmd.js index e36c194de..ab51e283e 100644 --- a/src/os/command/vectorlayercolorcmd.js +++ b/src/os/command/vectorlayercolorcmd.js @@ -31,8 +31,8 @@ os.command.VectorLayerColor = function(layerId, color, opt_oldColor, opt_changeM this.defaultColor = os.command.VectorLayerColor.DEFAULT_FILL_COLOR; break; case os.command.VectorLayerColor.MODE.STROKE: - this.title = 'Change Stroke Color'; - this.metricKey = os.metrics.Layer.VECTOR_STROKE_COLOR; + this.title = 'Change Color'; + this.metricKey = os.metrics.Layer.VECTOR_COLOR; this.defaultColor = os.command.VectorLayerColor.DEFAULT_COLOR; break; case os.command.VectorLayerColor.MODE.COMBINED: diff --git a/src/os/command/vectorlayeropacitycmd.js b/src/os/command/vectorlayeropacitycmd.js index e8f19442e..115ed8a2c 100644 --- a/src/os/command/vectorlayeropacitycmd.js +++ b/src/os/command/vectorlayeropacitycmd.js @@ -31,8 +31,8 @@ os.command.VectorLayerOpacity = function(layerId, opacity, opt_oldOpacity, opt_c this.defaultOpacity = os.command.VectorLayerOpacity.DEFAULT_FILL_OPACITY; break; case os.command.VectorLayerColor.MODE.STROKE: - this.title = 'Change Stroke Opacity'; - this.metricKey = os.metrics.Layer.VECTOR_STROKE_OPACITY; + this.title = 'Change Opacity'; + this.metricKey = os.metrics.Layer.VECTOR_OPACITY; this.defaultOpacity = os.command.VectorLayerOpacity.DEFAULT_OPACITY; break; case os.command.VectorLayerColor.MODE.COMBINED: diff --git a/src/os/metrics/layersmetrics.js b/src/os/metrics/layersmetrics.js index 0abf03758..b3e85defd 100644 --- a/src/os/metrics/layersmetrics.js +++ b/src/os/metrics/layersmetrics.js @@ -33,11 +33,6 @@ os.metrics.LayersMetrics = function() { description: 'The color used to render the data for this layer.', key: os.metrics.Layer.VECTOR_COLOR }); - this.addChild(styleLeaf, { - label: 'Change Feature Layer Stroke Color', - description: 'The stroke color used to render the data for this layer.', - key: os.metrics.Layer.VECTOR_STROKE_COLOR - }); this.addChild(styleLeaf, { label: 'Change Feature Layer Fill Color', description: 'The fill color used to render the data for this layer.', @@ -73,11 +68,6 @@ os.metrics.LayersMetrics = function() { description: 'The fill opacity used to render the data for this layer.', key: os.metrics.Layer.VECTOR_FILL_OPACITY }); - this.addChild(styleLeaf, { - label: 'Change Feature Layer Stroke Opacity', - description: 'The stroke opacity used to render the data for this layer.', - key: os.metrics.Layer.VECTOR_STROKE_OPACITY - }); this.addChild(styleLeaf, { label: 'Change Feature Layer Line Dash', description: 'The line dash for polygons and lines on this layer.', @@ -193,11 +183,6 @@ os.metrics.LayersMetrics = function() { description: 'The color used to render the data for this feature.', key: os.metrics.Layer.FEATURE_COLOR }); - this.addChild(styleLeaf, { - label: 'Change Feature Stroke Color', - description: 'The stroke color used to render the data for this feature.', - key: os.metrics.Layer.FEATURE_STROKE_COLOR - }); this.addChild(styleLeaf, { label: 'Change Feature Fill Color', description: 'The fill color used to render the data for this feature.', @@ -213,11 +198,6 @@ os.metrics.LayersMetrics = function() { description: 'The opacity used to render the data for this feature.', key: os.metrics.Layer.FEATURE_OPACITY }); - this.addChild(styleLeaf, { - label: 'Change Feature Stroke Opacity', - description: 'The stroke opacity used to render the data for this feature.', - key: os.metrics.Layer.FEATURE_STROKE_OPACITY - }); this.addChild(styleLeaf, { label: 'Change Feature Fill Opacity', description: 'The fill opacity used to render the data for this feature.', diff --git a/src/os/metrics/metricskeys.js b/src/os/metrics/metricskeys.js index 03763dc8a..c414ac0af 100644 --- a/src/os/metrics/metricskeys.js +++ b/src/os/metrics/metricskeys.js @@ -237,7 +237,6 @@ os.metrics.keys.OS = { os.metrics.Layer = { FORCE_LAYER_COLOR: 'layers.features.forceLayerColor', VECTOR_COLOR: 'layers.features.changeVectorColor', - VECTOR_STROKE_COLOR: 'layers.features.changeVectorStrokeColor', VECTOR_FILL_COLOR: 'layers.features.changeVectorFillColor', VECTOR_ICON: 'layers.features.changeVectorIcon', VECTOR_SHAPE: 'layers.features.changeVectorShape', @@ -245,7 +244,6 @@ os.metrics.Layer = { VECTOR_SIZE: 'layers.features.changeVectorSize', VECTOR_OPACITY: 'layers.features.changeVectorOpacity', VECTOR_FILL_OPACITY: 'layers.features.changeVectorFillOpacity', - VECTOR_STROKE_OPACITY: 'layers.features.changeVectorStrokeOpacity', VECTOR_LINE_DASH: 'layers.features.changeVectorLineDash', VECTOR_AUTO_REFRESH: 'layers.features.changeVectorAutoRefresh', VECTOR_ELLIPSOID: 'layers.features.changeVectorEllipsoid', @@ -269,11 +267,9 @@ os.metrics.Layer = { VECTOR_LOB_BEARING_ERROR_COLUMN: 'layers.features.changeVectorLineOfBearingBearingErrorColumn', VECTOR_ROTATION_COLUMN: 'layers.features.changeVectorRotationColumn', FEATURE_COLOR: 'layers.features.changeFeatureColor', - FEATURE_STROKE_COLOR: 'layers.features.changeFeatureStrokeColor', FEATURE_FILL_COLOR: 'layers.features.changeFeatureFillColor', FEATURE_ICON: 'layers.features.changeFeatureIcon', FEATURE_OPACITY: 'layers.features.changeFeatureOpacity', - FEATURE_STROKE_OPACITY: 'layers.features.changeFeatureStrokeOpacity', FEATURE_FILL_OPACITY: 'layers.features.changeFeatureFillOpacity', FEATURE_SIZE: 'layers.features.changeFeatureSize', FEATURE_LINE_DASH: 'layers.features.changeFeatureLineDash', From 09c2e270cc8a445c7d0d9a5de9d3f8cf2b9a685b Mon Sep 17 00:00:00 2001 From: Kevin Schmidt Date: Fri, 16 Aug 2019 17:42:52 -0600 Subject: [PATCH 17/28] fix(fa): match fill color to base color when loading old feature actions --- .../featureaction/featurestyleaction.js | 29 +++++++++++++++---- .../ui/featurestyleactionconfig.js | 9 +++--- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/plugin/featureaction/featurestyleaction.js b/src/plugin/featureaction/featurestyleaction.js index c930f9b0e..e8a934150 100644 --- a/src/plugin/featureaction/featurestyleaction.js +++ b/src/plugin/featureaction/featurestyleaction.js @@ -199,6 +199,17 @@ plugin.im.action.feature.StyleAction.prototype.persist = function(opt_to) { plugin.im.action.feature.StyleAction.prototype.restore = function(config) { var styleConfig = /** @type {Object|undefined} */ (config['styleConfig']); if (styleConfig) { + // if the style config is lacking a fill, it's an old config prior to fill support. use the base color with the + // default fill opacity. + if (styleConfig['fill'] === undefined) { + var color = os.style.getConfigColor(styleConfig); + if (color) { + color = os.color.toRgbArray(color); + color[3] = os.style.DEFAULT_FILL_ALPHA; + os.style.setFillColor(styleConfig, os.style.toRgbaString(color)); + } + } + // create a new object in the same window context as this object this.styleConfig = {}; os.object.merge(styleConfig, this.styleConfig); @@ -216,7 +227,7 @@ plugin.im.action.feature.StyleAction.prototype.toXml = function() { if (color) { os.xml.appendElement(plugin.im.action.feature.StyleActionTagName.COLOR, element, os.color.toHexString(color)); os.xml.appendElement(plugin.im.action.feature.StyleActionTagName.OPACITY, element, - String(color.length > 3 ? color[3] : 1.0)); + String(color.length > 3 ? color[3] : os.style.DEFAULT_ALPHA)); } var fillColor = /** @type {Array} */ @@ -225,7 +236,7 @@ plugin.im.action.feature.StyleAction.prototype.toXml = function() { os.xml.appendElement(plugin.im.action.feature.StyleActionTagName.FILL_COLOR, element, os.color.toHexString(fillColor)); os.xml.appendElement(plugin.im.action.feature.StyleActionTagName.FILL_OPACITY, element, - String(fillColor.length > 3 ? fillColor[3] : 0)); + String(fillColor.length > 3 ? fillColor[3] : os.style.DEFAULT_FILL_ALPHA)); } var size = os.style.getConfigSize(this.styleConfig); @@ -281,13 +292,14 @@ plugin.im.action.feature.StyleAction.prototype.fromXml = function(xml) { var styleConfig = /** @type {!Object} */ (os.object.unsafeClone(os.style.DEFAULT_VECTOR_CONFIG)); if (xml) { + var colorArr; var color = os.xml.getChildValue(xml, plugin.im.action.feature.StyleActionTagName.COLOR); if (os.color.isColorString(color)) { - var colorArr = os.color.toRgbArray(color); + colorArr = os.color.toRgbArray(color); if (colorArr) { var opacityVal = parseFloat( os.xml.getChildValue(xml, plugin.im.action.feature.StyleActionTagName.OPACITY)); - var opacity = !isNaN(opacityVal) ? goog.math.clamp(opacityVal, 0, 1) : 1.0; + var opacity = !isNaN(opacityVal) ? goog.math.clamp(opacityVal, 0, 1) : os.style.DEFAULT_ALPHA; colorArr[3] = opacity; color = os.style.toRgbaString(colorArr); } @@ -301,11 +313,18 @@ plugin.im.action.feature.StyleAction.prototype.fromXml = function(xml) { if (fillColorArr) { var fillOpacityVal = parseFloat( os.xml.getChildValue(xml, plugin.im.action.feature.StyleActionTagName.FILL_OPACITY)); - var fillOpacity = !isNaN(fillOpacityVal) ? goog.math.clamp(fillOpacityVal, 0, 1) : 1.0; + var fillOpacity = !isNaN(fillOpacityVal) ? goog.math.clamp(fillOpacityVal, 0, 1) : os.style.DEFAULT_FILL_ALPHA; fillColorArr[3] = fillOpacity; fillColor = os.style.toRgbaString(fillColorArr); } + } else if (colorArr) { + // No fill color in the XML, so use the base color with 0 opacity + var fillColorArr = colorArr.slice(); + fillColorArr[3] = 0; + fillColor = os.style.toRgbaString(fillColorArr); + } + if (os.color.isColorString(fillColor)) { // Only change the fill color without changing the image fill color too os.style.setFillColor(styleConfig, fillColor); } diff --git a/src/plugin/featureaction/ui/featurestyleactionconfig.js b/src/plugin/featureaction/ui/featurestyleactionconfig.js index 32deaa30d..793cd8994 100644 --- a/src/plugin/featureaction/ui/featurestyleactionconfig.js +++ b/src/plugin/featureaction/ui/featurestyleactionconfig.js @@ -143,7 +143,7 @@ plugin.im.action.feature.ui.StyleConfigCtrl.prototype.initialize = function() { this.scope['fillOpacity'] = fill[3]; } else { - this.scope['fillColor'] = os.color.toHexString(os.style.DEFAULT_FILL_COLOR); + this.scope['fillColor'] = os.color.toHexString(color || os.style.DEFAULT_FILL_COLOR); this.scope['fillOpacity'] = os.style.DEFAULT_FILL_ALPHA; fill = os.color.toRgbArray(this.scope['fillColor']); @@ -155,8 +155,7 @@ plugin.im.action.feature.ui.StyleConfigCtrl.prototype.initialize = function() { os.style.setConfigColor(this.styleConfig, strokeColor); // If we have a fill color, set that to our style config - var fillColor = os.style.toRgbaString(fill); - this.styleConfig.fill.color = fillColor; + os.style.setFillColor(this.styleConfig, os.style.toRgbaString(fill)); this.scope['size'] = os.style.getConfigSize(this.styleConfig); this.scope['lineDash'] = os.style.getConfigLineDash(this.styleConfig); @@ -253,7 +252,7 @@ plugin.im.action.feature.ui.StyleConfigCtrl.prototype.onColorChange = function(e this.scope['color'] = os.color.toHexString(color); // Only change the fill color without changing the image fill color too - this.styleConfig.fill.color = fillColor; + os.style.setFillColor(this.styleConfig, fillColor); this.scope['fillColor'] = os.color.toHexString(fillColor); } else { @@ -365,7 +364,7 @@ plugin.im.action.feature.ui.StyleConfigCtrl.prototype.onOpacityChange = function color[3] = value; // Only change the fill color without changing the image fill color too - this.styleConfig.fill.color = color; + os.style.setFillColor(this.styleConfig, color); this.scope['fillOpacity'] = value; } else { From 5d2e71fba0ee58791d7d0c7b63d677e8a758e79e Mon Sep 17 00:00:00 2001 From: Kevin Schmidt Date: Fri, 16 Aug 2019 18:07:24 -0600 Subject: [PATCH 18/28] fix(fill): reset fill opacity on command undo Also consolidated the color/opacity command change mode enums and replaced default opacity constants with os.style constants. --- src/os/command/feature/featurecolorcmd.js | 36 ++++----- src/os/command/feature/featureopacitycmd.js | 75 ++++++++----------- src/os/command/stylecommand.js | 12 +++ src/os/command/vectorlayercolorcmd.js | 56 +++++--------- src/os/command/vectorlayeropacitycmd.js | 82 ++++++++++++--------- src/os/ui/layer/vectorlayerui.js | 15 ++-- src/plugin/file/kml/kmlnodelayerui.js | 15 ++-- 7 files changed, 144 insertions(+), 147 deletions(-) create mode 100644 src/os/command/stylecommand.js diff --git a/src/os/command/feature/featurecolorcmd.js b/src/os/command/feature/featurecolorcmd.js index 09e4b8973..4cc94a032 100644 --- a/src/os/command/feature/featurecolorcmd.js +++ b/src/os/command/feature/featurecolorcmd.js @@ -1,8 +1,10 @@ goog.provide('os.command.FeatureColor'); goog.require('os.command.AbstractFeatureStyle'); +goog.require('os.command.style'); goog.require('os.events.PropertyChangeEvent'); goog.require('os.metrics'); +goog.require('os.style'); @@ -14,26 +16,31 @@ goog.require('os.metrics'); * @param {string} featureId * @param {Array|string} color * @param {(Array|string|null)=} opt_oldColor - * @param {string=} opt_changeMode + * @param {os.command.style.ColorChangeType=} opt_changeMode * @constructor */ os.command.FeatureColor = function(layerId, featureId, color, opt_oldColor, opt_changeMode) { - this.changeMode = opt_changeMode; + /** + * The color change mode. Determines how the config color is set. + * @type {os.command.style.ColorChangeType} + * @protected + */ + this.changeMode = opt_changeMode || os.command.style.ColorChangeType.COMBINED; os.command.FeatureColor.base(this, 'constructor', layerId, featureId, color, opt_oldColor); switch (this.changeMode) { - case os.command.FeatureColor.MODE.FILL: + case os.command.style.ColorChangeType.FILL: this.title = 'Change Feature Fill Color'; this.metricKey = os.metrics.Layer.FEATURE_FILL_COLOR; this.defaultColor = os.command.FeatureColor.DEFAULT_FILL_COLOR; break; - case os.command.FeatureColor.MODE.STROKE: + case os.command.style.ColorChangeType.STROKE: this.title = 'Change Feature Color'; this.metricKey = os.metrics.Layer.FEATURE_COLOR; this.defaultColor = os.command.FeatureColor.DEFAULT_COLOR; break; - case os.command.FeatureColor.MODE.COMBINED: + case os.command.style.ColorChangeType.COMBINED: default: this.title = 'Change Feature Color'; this.metricKey = os.metrics.Layer.FEATURE_COLOR; @@ -76,13 +83,6 @@ os.command.FeatureColor.DEFAULT_COLOR = 'rgba(255,255,255,1)'; os.command.FeatureColor.DEFAULT_FILL_COLOR = 'rgba(255,255,255,0)'; -os.command.FeatureColor.MODE = { - COMBINED: 'combined', - FILL: 'fill', - STROKE: 'stroke' -}; - - /** * @inheritDoc */ @@ -97,13 +97,13 @@ os.command.FeatureColor.prototype.getOldValue = function() { if (config) { switch (this.changeMode) { - case os.command.FeatureColor.MODE.FILL: + case os.command.style.ColorChangeType.FILL: ret = os.style.getConfigColor(config, false, os.style.StyleField.FILL); break; - case os.command.FeatureColor.MODE.STROKE: + case os.command.style.ColorChangeType.STROKE: ret = os.style.getConfigColor(config, false, os.style.StyleField.STROKE); break; - case os.command.FeatureColor.MODE.COMBINED: + case os.command.style.ColorChangeType.COMBINED: default: ret = os.style.getConfigColor(config); break; @@ -133,12 +133,12 @@ os.command.FeatureColor.prototype.applyValue = function(configs, value) { var color = os.style.toRgbaString(/** @type {string} */ (value)); switch (this.changeMode) { - case os.command.FeatureColor.MODE.FILL: + case os.command.style.ColorChangeType.FILL: for (var i = 0; i < configs.length; i++) { os.style.setFillColor(configs[i], color); } break; - case os.command.FeatureColor.MODE.STROKE: + case os.command.style.ColorChangeType.STROKE: for (var i = 0; i < configs.length; i++) { var fillColor = os.style.getConfigColor(configs[i], true, os.style.StyleField.FILL); @@ -153,7 +153,7 @@ os.command.FeatureColor.prototype.applyValue = function(configs, value) { this.applyLabelValue(configs, value); } break; - case os.command.FeatureColor.MODE.COMBINED: + case os.command.style.ColorChangeType.COMBINED: default: for (var i = 0; i < configs.length; i++) { os.style.setConfigColor(configs[i], color); diff --git a/src/os/command/feature/featureopacitycmd.js b/src/os/command/feature/featureopacitycmd.js index 7a2be3084..895b4de4f 100644 --- a/src/os/command/feature/featureopacitycmd.js +++ b/src/os/command/feature/featureopacitycmd.js @@ -1,9 +1,10 @@ goog.provide('os.command.FeatureOpacity'); goog.require('os.command.AbstractFeatureStyle'); +goog.require('os.command.style'); goog.require('os.events.PropertyChangeEvent'); goog.require('os.metrics'); -goog.require('os.ui'); +goog.require('os.style'); @@ -15,29 +16,35 @@ goog.require('os.ui'); * @param {string} featureId * @param {number} opacity * @param {number|null=} opt_oldOpacity - * @param {string=} opt_changeMode + * @param {os.command.style.ColorChangeType=} opt_changeMode * @constructor */ os.command.FeatureOpacity = function(layerId, featureId, opacity, opt_oldOpacity, opt_changeMode) { - this.changeMode = opt_changeMode; + /** + * The opacity change mode. Determines how the config opacity is set. + * @type {os.command.style.ColorChangeType} + * @protected + */ + this.changeMode = opt_changeMode || os.command.style.ColorChangeType.COMBINED; + os.command.FeatureOpacity.base(this, 'constructor', layerId, featureId, opacity, opt_oldOpacity); switch (this.changeMode) { - case os.command.FeatureOpacity.MODE.FILL: + case os.command.style.ColorChangeType.FILL: this.title = 'Change Feature Fill Opacity'; this.metricKey = os.metrics.Layer.FEATURE_FILL_OPACITY; - this.defaultOpacity = os.command.FeatureOpacity.DEFAULT_FILL_OPACITY; + this.defaultOpacity = os.style.DEFAULT_FILL_ALPHA; break; - case os.command.FeatureOpacity.MODE.STROKE: + case os.command.style.ColorChangeType.STROKE: this.title = 'Change Feature Opacity'; this.metricKey = os.metrics.Layer.FEATURE_OPACITY; - this.defaultOpacity = os.command.FeatureOpacity.DEFAULT_OPACITY; + this.defaultOpacity = os.style.DEFAULT_ALPHA; break; - case os.command.FeatureOpacity.MODE.COMBINED: + case os.command.style.ColorChangeType.COMBINED: default: this.title = 'Change Feature Opacity'; this.metricKey = os.metrics.Layer.FEATURE_OPACITY; - this.defaultOpacity = os.command.FeatureOpacity.DEFAULT_OPACITY; + this.defaultOpacity = os.style.DEFAULT_ALPHA; break; } @@ -46,7 +53,7 @@ os.command.FeatureOpacity = function(layerId, featureId, opacity, opt_oldOpacity var config = /** @type {Object|undefined} */ (feature.get(os.style.StyleType.FEATURE)); if (config) { - if (goog.isArray(config)) { + if (Array.isArray(config)) { config = config[0]; } opacity = /** @type {number} */ (os.style.getConfigOpacityColor(config)); @@ -58,57 +65,37 @@ os.command.FeatureOpacity = function(layerId, featureId, opacity, opt_oldOpacity goog.inherits(os.command.FeatureOpacity, os.command.AbstractFeatureStyle); -/** - * @type {number} - * @const - */ -os.command.FeatureOpacity.DEFAULT_OPACITY = 1; - - -/** - * @type {number} - * @const - */ -os.command.FeatureOpacity.DEFAULT_FILL_OPACITY = 0; - - -os.command.FeatureOpacity.MODE = { - COMBINED: 'combined', - FILL: 'fill', - STROKE: 'stroke' -}; - - /** * @inheritDoc */ os.command.FeatureOpacity.prototype.getOldValue = function() { var feature = /** @type {ol.Feature} */ (this.getFeature()); var config = /** @type {Array|Object|undefined} */ (this.getFeatureConfigs(feature)); - if (goog.isArray(config)) { + if (Array.isArray(config)) { config = config[0]; } var ret = this.defaultOpacity; if (config) { + var color; switch (this.changeMode) { - case os.command.FeatureOpacity.MODE.FILL: - var color = os.style.getConfigColor(config, true, os.style.StyleField.FILL); - if (color) { + case os.command.style.ColorChangeType.FILL: + color = os.style.getConfigColor(config, true, os.style.StyleField.FILL); + if (color && color.length === 4) { ret = color[3]; } break; - case os.command.FeatureOpacity.MODE.STROKE: - var color = os.style.getConfigColor(config, true, os.style.StyleField.STROKE); - if (color) { + case os.command.style.ColorChangeType.STROKE: + color = os.style.getConfigColor(config, true, os.style.StyleField.STROKE); + if (color && color.length === 4) { ret = color[3]; } break; - case os.command.FeatureOpacity.MODE.COMBINED: + case os.command.style.ColorChangeType.COMBINED: default: - var color = os.style.getConfigColor(config, true); - if (color) { + color = os.style.getConfigColor(config, true); + if (color && color.length === 4) { ret = color[3]; } break; @@ -128,7 +115,7 @@ os.command.FeatureOpacity.prototype.applyValue = function(configs, value) { var i; switch (this.changeMode) { - case os.command.FeatureOpacity.MODE.FILL: + case os.command.style.ColorChangeType.FILL: for (i = 0; i < configs.length; i++) { color = os.style.getConfigColor(configs[i], true, os.style.StyleField.FILL); color[3] = value; @@ -136,7 +123,7 @@ os.command.FeatureOpacity.prototype.applyValue = function(configs, value) { os.style.setConfigColor(configs[i], colorValue, [os.style.StyleField.FILL]); } break; - case os.command.FeatureOpacity.MODE.STROKE: + case os.command.style.ColorChangeType.STROKE: for (i = 0; i < configs.length; i++) { color = os.style.getConfigColor(configs[i], true, os.style.StyleField.STROKE); color[3] = value; @@ -150,7 +137,7 @@ os.command.FeatureOpacity.prototype.applyValue = function(configs, value) { } } break; - case os.command.FeatureOpacity.MODE.COMBINED: + case os.command.style.ColorChangeType.COMBINED: default: for (i = 0; i < configs.length; i++) { color = os.style.getConfigColor(configs[i], true); diff --git a/src/os/command/stylecommand.js b/src/os/command/stylecommand.js new file mode 100644 index 000000000..9f824367f --- /dev/null +++ b/src/os/command/stylecommand.js @@ -0,0 +1,12 @@ +goog.provide('os.command.style'); + + +/** + * Change types for color commands. Determines how color/opacity is set in style configs. + * @enum {string} + */ +os.command.style.ColorChangeType = { + COMBINED: 'combined', + FILL: 'fill', + STROKE: 'stroke' +}; diff --git a/src/os/command/vectorlayercolorcmd.js b/src/os/command/vectorlayercolorcmd.js index ab51e283e..8542c103f 100644 --- a/src/os/command/vectorlayercolorcmd.js +++ b/src/os/command/vectorlayercolorcmd.js @@ -1,11 +1,10 @@ goog.provide('os.command.VectorLayerColor'); goog.require('os.command.AbstractVectorStyle'); -goog.require('os.data.OSDataManager'); +goog.require('os.command.style'); goog.require('os.events.PropertyChangeEvent'); goog.require('os.metrics'); goog.require('os.source.PropertyChange'); -goog.require('os.ui'); @@ -16,30 +15,35 @@ goog.require('os.ui'); * @param {string} layerId * @param {Array|string} color * @param {(Array|string)=} opt_oldColor - * @param {string=} opt_changeMode + * @param {os.command.style.ColorChangeType=} opt_changeMode * @constructor */ os.command.VectorLayerColor = function(layerId, color, opt_oldColor, opt_changeMode) { - this.changeMode = opt_changeMode; + /** + * The color change mode. Determines how the config color is set. + * @type {os.command.style.ColorChangeType} + * @protected + */ + this.changeMode = opt_changeMode || os.command.style.ColorChangeType.COMBINED; os.command.VectorLayerColor.base(this, 'constructor', layerId, color, opt_oldColor); switch (this.changeMode) { - case os.command.VectorLayerColor.MODE.FILL: + case os.command.style.ColorChangeType.FILL: this.title = 'Change Fill Color'; this.metricKey = os.metrics.Layer.VECTOR_FILL_COLOR; - this.defaultColor = os.command.VectorLayerColor.DEFAULT_FILL_COLOR; + this.defaultColor = os.style.DEFAULT_FILL_COLOR; break; - case os.command.VectorLayerColor.MODE.STROKE: + case os.command.style.ColorChangeType.STROKE: this.title = 'Change Color'; this.metricKey = os.metrics.Layer.VECTOR_COLOR; - this.defaultColor = os.command.VectorLayerColor.DEFAULT_COLOR; + this.defaultColor = os.style.DEFAULT_LAYER_COLOR; break; - case os.command.VectorLayerColor.MODE.COMBINED: + case os.command.style.ColorChangeType.COMBINED: default: this.title = 'Change Color'; this.metricKey = os.metrics.Layer.VECTOR_COLOR; - this.defaultColor = os.command.VectorLayerColor.DEFAULT_COLOR; + this.defaultColor = os.style.DEFAULT_LAYER_COLOR; break; } @@ -57,26 +61,6 @@ os.command.VectorLayerColor = function(layerId, color, opt_oldColor, opt_changeM goog.inherits(os.command.VectorLayerColor, os.command.AbstractVectorStyle); -/** - * @type {string} - * @const - */ -os.command.VectorLayerColor.DEFAULT_COLOR = 'rgba(255,255,255,1)'; - - -/** - * @type {string} - * @const - */ -os.command.VectorLayerColor.DEFAULT_FILL_COLOR = 'rgba(255,255,255,0)'; - - -os.command.VectorLayerColor.MODE = { - COMBINED: 'combined', - FILL: 'fill', - STROKE: 'stroke' -}; - /** * @inheritDoc */ @@ -86,13 +70,13 @@ os.command.VectorLayerColor.prototype.getOldValue = function() { if (config) { switch (this.changeMode) { - case os.command.VectorLayerColor.MODE.FILL: + case os.command.style.ColorChangeType.FILL: ret = os.style.getConfigColor(config, false, os.style.StyleField.FILL); break; - case os.command.VectorLayerColor.MODE.STROKE: + case os.command.style.ColorChangeType.STROKE: ret = os.style.getConfigColor(config, false, os.style.StyleField.STROKE); break; - case os.command.VectorLayerColor.MODE.COMBINED: + case os.command.style.ColorChangeType.COMBINED: default: ret = os.style.getConfigColor(config); break; @@ -112,7 +96,7 @@ os.command.VectorLayerColor.prototype.applyValue = function(config, value) { var color = os.style.toRgbaString(/** @type {string} */ (value)); switch (this.changeMode) { - case os.command.VectorLayerColor.MODE.FILL: + case os.command.style.ColorChangeType.FILL: os.style.setFillColor(config, color); // Make sure the fill color and opacity are updated as well @@ -120,7 +104,7 @@ os.command.VectorLayerColor.prototype.applyValue = function(config, value) { config['fillColor'] = color; } break; - case os.command.VectorLayerColor.MODE.STROKE: + case os.command.style.ColorChangeType.STROKE: os.style.setConfigColor(config, color); if (config['fillColor']) { @@ -129,7 +113,7 @@ os.command.VectorLayerColor.prototype.applyValue = function(config, value) { os.ui.adjustIconSet(this.layerId, color); break; - case os.command.VectorLayerColor.MODE.COMBINED: + case os.command.style.ColorChangeType.COMBINED: default: os.style.setConfigColor(config, color); diff --git a/src/os/command/vectorlayeropacitycmd.js b/src/os/command/vectorlayeropacitycmd.js index 115ed8a2c..2861e1b10 100644 --- a/src/os/command/vectorlayeropacitycmd.js +++ b/src/os/command/vectorlayeropacitycmd.js @@ -1,11 +1,10 @@ goog.provide('os.command.VectorLayerOpacity'); goog.require('os.command.AbstractVectorStyle'); -goog.require('os.data.OSDataManager'); +goog.require('os.command.style'); goog.require('os.events.PropertyChangeEvent'); goog.require('os.metrics'); goog.require('os.source.PropertyChange'); -goog.require('os.ui'); @@ -16,30 +15,35 @@ goog.require('os.ui'); * @param {string} layerId * @param {number} opacity * @param {number|null=} opt_oldOpacity - * @param {string=} opt_changeMode + * @param {os.command.style.ColorChangeType=} opt_changeMode * @constructor */ os.command.VectorLayerOpacity = function(layerId, opacity, opt_oldOpacity, opt_changeMode) { - os.command.VectorLayerOpacity.base(this, 'constructor', layerId, opacity, opt_oldOpacity); + /** + * The opacity change mode. Determines how the config opacity is set. + * @type {os.command.style.ColorChangeType} + * @protected + */ + this.changeMode = opt_changeMode || os.command.style.ColorChangeType.COMBINED; - this.changeMode = opt_changeMode; + os.command.VectorLayerOpacity.base(this, 'constructor', layerId, opacity, opt_oldOpacity); switch (this.changeMode) { - case os.command.VectorLayerColor.MODE.FILL: + case os.command.style.ColorChangeType.FILL: this.title = 'Change Fill Opacity'; this.metricKey = os.metrics.Layer.VECTOR_FILL_OPACITY; - this.defaultOpacity = os.command.VectorLayerOpacity.DEFAULT_FILL_OPACITY; + this.defaultOpacity = os.style.DEFAULT_FILL_ALPHA; break; - case os.command.VectorLayerColor.MODE.STROKE: + case os.command.style.ColorChangeType.STROKE: this.title = 'Change Opacity'; this.metricKey = os.metrics.Layer.VECTOR_OPACITY; - this.defaultOpacity = os.command.VectorLayerOpacity.DEFAULT_OPACITY; + this.defaultOpacity = os.style.DEFAULT_ALPHA; break; - case os.command.VectorLayerColor.MODE.COMBINED: + case os.command.style.ColorChangeType.COMBINED: default: this.title = 'Change Opacity'; this.metricKey = os.metrics.Layer.VECTOR_OPACITY; - this.defaultOpacity = os.command.VectorLayerOpacity.DEFAULT_OPACITY; + this.defaultOpacity = os.style.DEFAULT_ALPHA; break; } @@ -57,33 +61,39 @@ os.command.VectorLayerOpacity = function(layerId, opacity, opt_oldOpacity, opt_c goog.inherits(os.command.VectorLayerOpacity, os.command.AbstractVectorStyle); -/** - * @type {number} - * @const - */ -os.command.VectorLayerOpacity.DEFAULT_OPACITY = 1; - - -/** - * @type {number} - * @const - */ -os.command.VectorLayerOpacity.DEFAULT_FILL_OPACITY = 0; - - -os.command.VectorLayerOpacity.MODE = { - COMBINED: 'combined', - FILL: 'fill', - STROKE: 'stroke' -}; - - /** * @inheritDoc */ os.command.VectorLayerOpacity.prototype.getOldValue = function() { var config = os.style.StyleManager.getInstance().getLayerConfig(this.layerId); - return config ? os.style.getConfigOpacityColor(config) : this.defaultOpacity; + var ret = this.defaultOpacity; + + if (config) { + var color; + switch (this.changeMode) { + case os.command.style.ColorChangeType.FILL: + color = os.style.getConfigColor(config, true, os.style.StyleField.FILL); + if (color && color.length === 4) { + ret = color[3]; + } + break; + case os.command.style.ColorChangeType.STROKE: + color = os.style.getConfigColor(config, true, os.style.StyleField.STROKE); + if (color && color.length === 4) { + ret = color[3]; + } + break; + case os.command.style.ColorChangeType.COMBINED: + default: + color = os.style.getConfigColor(config, true); + if (color && color.length === 4) { + ret = color[3]; + } + break; + } + } + + return ret; }; @@ -95,7 +105,7 @@ os.command.VectorLayerOpacity.prototype.applyValue = function(config, value) { var colorString; switch (this.changeMode) { - case os.command.VectorLayerOpacity.MODE.FILL: + case os.command.style.ColorChangeType.FILL: color = os.style.getConfigColor(config, true, os.style.StyleField.FILL); color[3] = value; colorString = os.style.toRgbaString(color); @@ -111,7 +121,7 @@ os.command.VectorLayerOpacity.prototype.applyValue = function(config, value) { } break; - case os.command.VectorLayerOpacity.MODE.STROKE: + case os.command.style.ColorChangeType.STROKE: color = os.style.getConfigColor(config, true, os.style.StyleField.STROKE); color[3] = value; colorString = os.style.toRgbaString(color); @@ -125,7 +135,7 @@ os.command.VectorLayerOpacity.prototype.applyValue = function(config, value) { os.ui.adjustIconSet(this.layerId, color); break; - case os.command.VectorLayerOpacity.MODE.COMBINED: + case os.command.style.ColorChangeType.COMBINED: default: color = os.style.getConfigColor(config, true); color[3] = value; diff --git a/src/os/ui/layer/vectorlayerui.js b/src/os/ui/layer/vectorlayerui.js index 294d7c65d..3c62d6b2b 100644 --- a/src/os/ui/layer/vectorlayerui.js +++ b/src/os/ui/layer/vectorlayerui.js @@ -22,6 +22,7 @@ goog.require('os.command.VectorLayerShowLabel'); goog.require('os.command.VectorLayerShowRotation'); goog.require('os.command.VectorLayerSize'); goog.require('os.command.VectorUniqueIdCmd'); +goog.require('os.command.style'); goog.require('os.data.OSDataManager'); goog.require('os.defines'); goog.require('os.style'); @@ -353,7 +354,7 @@ os.ui.layer.VectorLayerUICtrl.prototype.onColorChange = function(event, value) { */ function(layer) { return new os.command.VectorLayerColor( - layer.getId(), colorValue, null, os.command.VectorLayerColor.MODE.COMBINED); + layer.getId(), colorValue, null, os.command.style.ColorChangeType.COMBINED); }; this.createCommand(fn); @@ -373,10 +374,10 @@ os.ui.layer.VectorLayerUICtrl.prototype.onColorChange = function(event, value) { var cmds = []; cmds.push(new os.command.VectorLayerColor( - layer.getId(), strokeArray, null, os.command.VectorLayerColor.MODE.STROKE) + layer.getId(), strokeArray, null, os.command.style.ColorChangeType.STROKE) ); cmds.push(new os.command.VectorLayerColor( - layer.getId(), fillArray, null, os.command.VectorLayerColor.MODE.FILL) + layer.getId(), fillArray, null, os.command.style.ColorChangeType.FILL) ); var sequence = new os.command.SequenceCommand(); @@ -395,7 +396,7 @@ os.ui.layer.VectorLayerUICtrl.prototype.onColorChange = function(event, value) { */ function(layer) { return new os.command.VectorLayerColor( - layer.getId(), colorValue, null, os.command.VectorLayerColor.MODE.STROKE); + layer.getId(), colorValue, null, os.command.style.ColorChangeType.STROKE); }; this.createCommand(fn3); @@ -444,7 +445,7 @@ os.ui.layer.VectorLayerUICtrl.prototype.onFillColorChange = function(event, valu */ function(layer) { return new os.command.VectorLayerColor( - layer.getId(), colorValue, null, os.command.VectorLayerColor.MODE.FILL); + layer.getId(), colorValue, null, os.command.style.ColorChangeType.FILL); }; this.createCommand(fn); @@ -512,7 +513,7 @@ os.ui.layer.VectorLayerUICtrl.prototype.onSliderStop = function(callback, key, e */ function(layer) { return new os.command.VectorLayerOpacity( - layer.getId(), value, null, os.command.VectorLayerOpacity.MODE.FILL); + layer.getId(), value, null, os.command.style.ColorChangeType.FILL); }; this.createCommand(fn); @@ -535,7 +536,7 @@ os.ui.layer.VectorLayerUICtrl.prototype.onSliderStop = function(callback, key, e */ function(layer) { return new os.command.VectorLayerOpacity( - layer.getId(), value, null, os.command.VectorLayerOpacity.MODE.STROKE); + layer.getId(), value, null, os.command.style.ColorChangeType.STROKE); }; this.createCommand(fn3); diff --git a/src/plugin/file/kml/kmlnodelayerui.js b/src/plugin/file/kml/kmlnodelayerui.js index 81924b728..65338cba5 100644 --- a/src/plugin/file/kml/kmlnodelayerui.js +++ b/src/plugin/file/kml/kmlnodelayerui.js @@ -15,6 +15,7 @@ goog.require('os.command.FeatureShowLabel'); goog.require('os.command.FeatureSize'); goog.require('os.command.ParallelCommand'); goog.require('os.command.SequenceCommand'); +goog.require('os.command.style'); goog.require('os.data.ColumnDefinition'); goog.require('os.geo'); goog.require('os.ui.Module'); @@ -624,10 +625,10 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onColorChange = function(event, val var cmds = []; cmds.push(new os.command.FeatureColor( - layerId, featureId, strokeColor, null, os.command.FeatureColor.MODE.STROKE) + layerId, featureId, strokeColor, null, os.command.style.ColorChangeType.STROKE) ); cmds.push(new os.command.FeatureColor( - layerId, featureId, fillColor, null, os.command.FeatureColor.MODE.FILL) + layerId, featureId, fillColor, null, os.command.style.ColorChangeType.FILL) ); var sequence = new os.command.SequenceCommand(); @@ -647,7 +648,8 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onColorChange = function(event, val * @return {os.command.ICommand} */ function(layerId, featureId) { - return new os.command.FeatureColor(layerId, featureId, colorValue, null, os.command.FeatureColor.MODE.STROKE); + return new os.command.FeatureColor(layerId, featureId, colorValue, null, + os.command.style.ColorChangeType.STROKE); }; this.createFeatureCommand(fn3); @@ -691,7 +693,7 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onFillColorChange = function(event, * @return {os.command.ICommand} */ function(layerId, featureId) { - return new os.command.FeatureColor(layerId, featureId, colorValue, null, os.command.FeatureColor.MODE.FILL); + return new os.command.FeatureColor(layerId, featureId, colorValue, null, os.command.style.ColorChangeType.FILL); }; this.createFeatureCommand(fn); @@ -833,7 +835,8 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onOpacityChange = function(event, v * @return {os.command.ICommand} */ function(layerId, featureId) { - return new os.command.FeatureOpacity(layerId, featureId, value, null, os.command.FeatureOpacity.MODE.STROKE); + return new os.command.FeatureOpacity(layerId, featureId, value, null, + os.command.style.ColorChangeType.STROKE); }; this.createFeatureCommand(fn2); @@ -859,7 +862,7 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onFillOpacityChange = function(even * @return {os.command.ICommand} */ function(layerId, featureId) { - return new os.command.FeatureOpacity(layerId, featureId, value, null, os.command.FeatureOpacity.MODE.FILL); + return new os.command.FeatureOpacity(layerId, featureId, value, null, os.command.style.ColorChangeType.FILL); }; this.createFeatureCommand(fn); From f25409b096dcbe644d3333150f0d0b69e36c153c Mon Sep 17 00:00:00 2001 From: Kevin Schmidt Date: Fri, 16 Aug 2019 18:53:26 -0600 Subject: [PATCH 19/28] fix(fill): default KML fill color/opacity appropriately Also fixed some additional opacity command quirks. --- src/os/command/feature/featurecolorcmd.js | 1 + src/os/command/feature/featureopacitycmd.js | 78 +++++++-------- src/os/command/vectorlayercolorcmd.js | 1 + src/os/command/vectorlayeropacitycmd.js | 100 +++++++++----------- src/os/ui/layer/vectorlayerui.js | 4 +- src/plugin/file/kml/kmlnodelayerui.js | 15 +-- 6 files changed, 87 insertions(+), 112 deletions(-) diff --git a/src/os/command/feature/featurecolorcmd.js b/src/os/command/feature/featurecolorcmd.js index 4cc94a032..85110d14a 100644 --- a/src/os/command/feature/featurecolorcmd.js +++ b/src/os/command/feature/featurecolorcmd.js @@ -27,6 +27,7 @@ os.command.FeatureColor = function(layerId, featureId, color, opt_oldColor, opt_ */ this.changeMode = opt_changeMode || os.command.style.ColorChangeType.COMBINED; + // intentionally called after changeMode is set so getOldValue has the correct value os.command.FeatureColor.base(this, 'constructor', layerId, featureId, color, opt_oldColor); switch (this.changeMode) { diff --git a/src/os/command/feature/featureopacitycmd.js b/src/os/command/feature/featureopacitycmd.js index 895b4de4f..9a4defdf4 100644 --- a/src/os/command/feature/featureopacitycmd.js +++ b/src/os/command/feature/featureopacitycmd.js @@ -1,5 +1,6 @@ goog.provide('os.command.FeatureOpacity'); +goog.require('goog.asserts'); goog.require('os.command.AbstractFeatureStyle'); goog.require('os.command.style'); goog.require('os.events.PropertyChangeEvent'); @@ -20,6 +21,8 @@ goog.require('os.style'); * @constructor */ os.command.FeatureOpacity = function(layerId, featureId, opacity, opt_oldOpacity, opt_changeMode) { + goog.asserts.assert(opacity != null, 'opacity must be defined'); + /** * The opacity change mode. Determines how the config opacity is set. * @type {os.command.style.ColorChangeType} @@ -27,40 +30,24 @@ os.command.FeatureOpacity = function(layerId, featureId, opacity, opt_oldOpacity */ this.changeMode = opt_changeMode || os.command.style.ColorChangeType.COMBINED; + // intentionally called after changeMode is set so getOldValue has the correct value os.command.FeatureOpacity.base(this, 'constructor', layerId, featureId, opacity, opt_oldOpacity); switch (this.changeMode) { case os.command.style.ColorChangeType.FILL: this.title = 'Change Feature Fill Opacity'; this.metricKey = os.metrics.Layer.FEATURE_FILL_OPACITY; - this.defaultOpacity = os.style.DEFAULT_FILL_ALPHA; break; case os.command.style.ColorChangeType.STROKE: this.title = 'Change Feature Opacity'; this.metricKey = os.metrics.Layer.FEATURE_OPACITY; - this.defaultOpacity = os.style.DEFAULT_ALPHA; break; case os.command.style.ColorChangeType.COMBINED: default: this.title = 'Change Feature Opacity'; this.metricKey = os.metrics.Layer.FEATURE_OPACITY; - this.defaultOpacity = os.style.DEFAULT_ALPHA; break; } - - if (!opacity) { - var feature = this.getFeature(); - var config = /** @type {Object|undefined} */ (feature.get(os.style.StyleType.FEATURE)); - - if (config) { - if (Array.isArray(config)) { - config = config[0]; - } - opacity = /** @type {number} */ (os.style.getConfigOpacityColor(config)); - } - } - - this.value = opacity; }; goog.inherits(os.command.FeatureOpacity, os.command.AbstractFeatureStyle); @@ -69,35 +56,28 @@ goog.inherits(os.command.FeatureOpacity, os.command.AbstractFeatureStyle); * @inheritDoc */ os.command.FeatureOpacity.prototype.getOldValue = function() { + var ret; var feature = /** @type {ol.Feature} */ (this.getFeature()); var config = /** @type {Array|Object|undefined} */ (this.getFeatureConfigs(feature)); if (Array.isArray(config)) { config = config[0]; } - var ret = this.defaultOpacity; - if (config) { var color; switch (this.changeMode) { case os.command.style.ColorChangeType.FILL: color = os.style.getConfigColor(config, true, os.style.StyleField.FILL); - if (color && color.length === 4) { - ret = color[3]; - } + ret = color && color.length === 4 ? color[3] : os.style.DEFAULT_FILL_ALPHA; break; case os.command.style.ColorChangeType.STROKE: color = os.style.getConfigColor(config, true, os.style.StyleField.STROKE); - if (color && color.length === 4) { - ret = color[3]; - } + ret = color && color.length === 4 ? color[3] : os.style.DEFAULT_ALPHA; break; case os.command.style.ColorChangeType.COMBINED: default: color = os.style.getConfigColor(config, true); - if (color && color.length === 4) { - ret = color[3]; - } + ret = color && color.length === 4 ? color[3] : os.style.DEFAULT_ALPHA; break; } } @@ -117,23 +97,30 @@ os.command.FeatureOpacity.prototype.applyValue = function(configs, value) { switch (this.changeMode) { case os.command.style.ColorChangeType.FILL: for (i = 0; i < configs.length; i++) { - color = os.style.getConfigColor(configs[i], true, os.style.StyleField.FILL); - color[3] = value; - colorValue = os.style.toRgbaString(color); - os.style.setConfigColor(configs[i], colorValue, [os.style.StyleField.FILL]); + color = os.style.getConfigColor(configs[i], true, os.style.StyleField.FILL) || + os.style.getConfigColor(configs[i], true); + + if (color) { + color[3] = value; + colorValue = os.style.toRgbaString(color); + os.style.setFillColor(configs[i], colorValue); + } } break; case os.command.style.ColorChangeType.STROKE: for (i = 0; i < configs.length; i++) { - color = os.style.getConfigColor(configs[i], true, os.style.StyleField.STROKE); - color[3] = value; - colorValue = os.style.toRgbaString(color); - var fillColor = os.style.getConfigColor(configs[i], true, os.style.StyleField.FILL); - - os.style.setConfigColor(configs[i], colorValue); - - if (fillColor) { - os.style.setFillColor(configs[i], fillColor); + color = os.style.getConfigColor(configs[i], true, os.style.StyleField.STROKE) || + os.style.getConfigColor(configs[i], true); + + if (color) { + color[3] = value; + colorValue = os.style.toRgbaString(color); + os.style.setConfigColor(configs[i], colorValue); + + var fillColor = os.style.getConfigColor(configs[i], true, os.style.StyleField.FILL); + if (fillColor) { + os.style.setFillColor(configs[i], fillColor); + } } } break; @@ -141,9 +128,12 @@ os.command.FeatureOpacity.prototype.applyValue = function(configs, value) { default: for (i = 0; i < configs.length; i++) { color = os.style.getConfigColor(configs[i], true); - color[3] = value; - colorValue = os.style.toRgbaString(color); - os.style.setConfigColor(configs[i], colorValue); + + if (color) { + color[3] = value; + colorValue = os.style.toRgbaString(color); + os.style.setConfigColor(configs[i], colorValue); + } } break; } diff --git a/src/os/command/vectorlayercolorcmd.js b/src/os/command/vectorlayercolorcmd.js index 8542c103f..4712fa699 100644 --- a/src/os/command/vectorlayercolorcmd.js +++ b/src/os/command/vectorlayercolorcmd.js @@ -26,6 +26,7 @@ os.command.VectorLayerColor = function(layerId, color, opt_oldColor, opt_changeM */ this.changeMode = opt_changeMode || os.command.style.ColorChangeType.COMBINED; + // intentionally called after changeMode is set so getOldValue has the correct value os.command.VectorLayerColor.base(this, 'constructor', layerId, color, opt_oldColor); switch (this.changeMode) { diff --git a/src/os/command/vectorlayeropacitycmd.js b/src/os/command/vectorlayeropacitycmd.js index 2861e1b10..90045420e 100644 --- a/src/os/command/vectorlayeropacitycmd.js +++ b/src/os/command/vectorlayeropacitycmd.js @@ -1,5 +1,6 @@ goog.provide('os.command.VectorLayerOpacity'); +goog.require('goog.asserts'); goog.require('os.command.AbstractVectorStyle'); goog.require('os.command.style'); goog.require('os.events.PropertyChangeEvent'); @@ -19,6 +20,8 @@ goog.require('os.source.PropertyChange'); * @constructor */ os.command.VectorLayerOpacity = function(layerId, opacity, opt_oldOpacity, opt_changeMode) { + goog.asserts.assert(opacity != null, 'opacity must be defined'); + /** * The opacity change mode. Determines how the config opacity is set. * @type {os.command.style.ColorChangeType} @@ -26,37 +29,24 @@ os.command.VectorLayerOpacity = function(layerId, opacity, opt_oldOpacity, opt_c */ this.changeMode = opt_changeMode || os.command.style.ColorChangeType.COMBINED; + // intentionally called after changeMode is set so getOldValue has the correct value os.command.VectorLayerOpacity.base(this, 'constructor', layerId, opacity, opt_oldOpacity); switch (this.changeMode) { case os.command.style.ColorChangeType.FILL: this.title = 'Change Fill Opacity'; this.metricKey = os.metrics.Layer.VECTOR_FILL_OPACITY; - this.defaultOpacity = os.style.DEFAULT_FILL_ALPHA; break; case os.command.style.ColorChangeType.STROKE: this.title = 'Change Opacity'; this.metricKey = os.metrics.Layer.VECTOR_OPACITY; - this.defaultOpacity = os.style.DEFAULT_ALPHA; break; case os.command.style.ColorChangeType.COMBINED: default: this.title = 'Change Opacity'; this.metricKey = os.metrics.Layer.VECTOR_OPACITY; - this.defaultOpacity = os.style.DEFAULT_ALPHA; break; } - - if (!opacity) { - opacity = this.defaultOpacity; - var layer = /** @type {os.layer.Vector} */ (os.MapContainer.getInstance().getLayer(this.layerId)); - if (layer) { - var options = layer.getLayerOptions(); - if (options && options['baseOpacity']) { - opacity = /** @type {number} */ (options['baseOpacity']); - } - } - } }; goog.inherits(os.command.VectorLayerOpacity, os.command.AbstractVectorStyle); @@ -66,29 +56,23 @@ goog.inherits(os.command.VectorLayerOpacity, os.command.AbstractVectorStyle); */ os.command.VectorLayerOpacity.prototype.getOldValue = function() { var config = os.style.StyleManager.getInstance().getLayerConfig(this.layerId); - var ret = this.defaultOpacity; + var ret; if (config) { var color; switch (this.changeMode) { case os.command.style.ColorChangeType.FILL: color = os.style.getConfigColor(config, true, os.style.StyleField.FILL); - if (color && color.length === 4) { - ret = color[3]; - } + ret = color && color.length === 4 ? color[3] : os.style.DEFAULT_FILL_ALPHA; break; case os.command.style.ColorChangeType.STROKE: color = os.style.getConfigColor(config, true, os.style.StyleField.STROKE); - if (color && color.length === 4) { - ret = color[3]; - } + ret = color && color.length === 4 ? color[3] : os.style.DEFAULT_ALPHA; break; case os.command.style.ColorChangeType.COMBINED: default: color = os.style.getConfigColor(config, true); - if (color && color.length === 4) { - ret = color[3]; - } + ret = color && color.length === 4 ? color[3] : os.style.DEFAULT_ALPHA; break; } } @@ -106,53 +90,61 @@ os.command.VectorLayerOpacity.prototype.applyValue = function(config, value) { switch (this.changeMode) { case os.command.style.ColorChangeType.FILL: - color = os.style.getConfigColor(config, true, os.style.StyleField.FILL); - color[3] = value; - colorString = os.style.toRgbaString(color); + color = os.style.getConfigColor(config, true, os.style.StyleField.FILL) || + os.style.getConfigColor(config, true); - os.style.setFillColor(config, colorString); + if (color) { + color[3] = value; + colorString = os.style.toRgbaString(color); - // Make sure the fill color and opacity are updated as well - if (config['fillColor']) { - config['fillColor'] = colorString; - } - if (config['fillOpacity'] !== undefined) { - config['fillOpacity'] = value; - } + os.style.setFillColor(config, colorString); + // Make sure the fill color and opacity are updated as well + if (config['fillColor']) { + config['fillColor'] = colorString; + } + if (config['fillOpacity'] !== undefined) { + config['fillOpacity'] = value; + } + } break; case os.command.style.ColorChangeType.STROKE: - color = os.style.getConfigColor(config, true, os.style.StyleField.STROKE); - color[3] = value; - colorString = os.style.toRgbaString(color); + color = os.style.getConfigColor(config, true, os.style.StyleField.STROKE) || + os.style.getConfigColor(config, true); - os.style.setConfigColor(config, color); + if (color) { + color[3] = value; + colorString = os.style.toRgbaString(color); - if (config['fillColor']) { - os.style.setFillColor(config, config['fillColor']); - } + os.style.setConfigColor(config, color); - os.ui.adjustIconSet(this.layerId, color); + if (config['fillColor']) { + os.style.setFillColor(config, config['fillColor']); + } + os.ui.adjustIconSet(this.layerId, color); + } break; case os.command.style.ColorChangeType.COMBINED: default: color = os.style.getConfigColor(config, true); - color[3] = value; - colorString = os.style.toRgbaString(color); - os.style.setConfigColor(config, colorString); + if (color) { + color[3] = value; + colorString = os.style.toRgbaString(color); - // Make sure the fill color and opacity are updated as well - if (config['fillColor']) { - config['fillColor'] = colorString; - } - if (config['fillOpacity'] !== undefined) { - config['fillOpacity'] = value; - } + os.style.setConfigColor(config, colorString); - os.ui.adjustIconSet(this.layerId, color); + // Make sure the fill color and opacity are updated as well + if (config['fillColor']) { + config['fillColor'] = colorString; + } + if (config['fillOpacity'] !== undefined) { + config['fillOpacity'] = value; + } + os.ui.adjustIconSet(this.layerId, color); + } break; } diff --git a/src/os/ui/layer/vectorlayerui.js b/src/os/ui/layer/vectorlayerui.js index 3c62d6b2b..4e21ef780 100644 --- a/src/os/ui/layer/vectorlayerui.js +++ b/src/os/ui/layer/vectorlayerui.js @@ -185,7 +185,7 @@ os.ui.layer.VectorLayerUICtrl.prototype.initUI = function() { this.scope['centerShape'] = this.getCenterShape(); this.scope['centerShapes'] = this.getCenterShapes(); this.scope['lockable'] = this.getLockable(); - this.scope['fillColor'] = this.getFillColor(); + this.scope['fillColor'] = this.getFillColor() || this.scope['color']; this.scope['fillOpacity'] = this.getFillOpacity(); this['altitudeMode'] = this.getAltitudeMode(); this['columns'] = this.getColumns(); @@ -820,8 +820,6 @@ os.ui.layer.VectorLayerUICtrl.prototype.getFillColor = function() { if (config) { var color = os.style.getConfigColor(config, false, os.style.StyleField.FILL); - color = color || os.style.DEFAULT_LAYER_COLOR; - if (color) { return os.color.toHexString(color); } diff --git a/src/plugin/file/kml/kmlnodelayerui.js b/src/plugin/file/kml/kmlnodelayerui.js index 65338cba5..7ddc67eca 100644 --- a/src/plugin/file/kml/kmlnodelayerui.js +++ b/src/plugin/file/kml/kmlnodelayerui.js @@ -133,14 +133,9 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.getProperties = function() { plugin.file.kml.KMLNodeLayerUICtrl.prototype.initUI = function() { plugin.file.kml.KMLNodeLayerUICtrl.base(this, 'initUI'); - if (this.scope) { - if (this.isFeatureFillable()) { - this.scope['fillColor'] = this.getFillColor(); - this.scope['fillOpacity'] = this.getFillOpacity(); - } else { - delete this.scope['fillColor']; - delete this.scope['fillOpacity']; - } + if (this.scope && !this.isFeatureFillable()) { + delete this.scope['fillColor']; + delete this.scope['fillOpacity']; } }; @@ -193,8 +188,6 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.getFillColor = function() { } var color = os.style.getConfigColor(config, false, os.style.StyleField.FILL); - color = color || os.style.DEFAULT_LAYER_COLOR; - if (color) { return os.color.toHexString(color); } @@ -212,7 +205,7 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.getFillColor = function() { */ plugin.file.kml.KMLNodeLayerUICtrl.prototype.getFillOpacity = function() { var items = /** @type {Array} */ (this.scope['items']); - var opacity = os.style.DEFAULT_ALPHA; + var opacity = os.style.DEFAULT_FILL_ALPHA; if (items) { for (var i = 0, n = items.length; i < n; i++) { From 73cf6d090a6c49e08cb9a8021a60595ae5d76938 Mon Sep 17 00:00:00 2001 From: Kevin Schmidt Date: Fri, 16 Aug 2019 19:10:28 -0600 Subject: [PATCH 20/28] fix(fill): unlink opacity and fill opacity sliders --- src/os/ui/layer/vectorlayerui.js | 55 +++++----------------- src/plugin/file/kml/kmlnodelayerui.js | 68 ++++++++++----------------- 2 files changed, 36 insertions(+), 87 deletions(-) diff --git a/src/os/ui/layer/vectorlayerui.js b/src/os/ui/layer/vectorlayerui.js index 4e21ef780..2513dcd44 100644 --- a/src/os/ui/layer/vectorlayerui.js +++ b/src/os/ui/layer/vectorlayerui.js @@ -481,14 +481,6 @@ os.ui.layer.VectorLayerUICtrl.prototype.onValueChange = function(callback, event if (event.name == 'fillOpacity.slide') { this.scope['fillOpacity'] = value; } else { - if (this.scope['fillOpacity'] !== undefined && this.scope['opacity'] == this.scope['fillOpacity']) { - var color = os.color.toHexString(this.scope['color']); - var fillColor = os.color.toHexString(this.scope['fillColor']); - if (color == fillColor) { - this.scope['fillOpacity'] = value; - } - } - this.scope['opacity'] = value; } }; @@ -497,7 +489,7 @@ os.ui.layer.VectorLayerUICtrl.prototype.onValueChange = function(callback, event * @inheritDoc */ os.ui.layer.VectorLayerUICtrl.prototype.onSliderStop = function(callback, key, event, value) { - // If we are not dealing with opacity of fill opacity, let the parent handle this event + // If we are not dealing with opacity or fill opacity, let the parent handle this event if (event.name != 'opacity.slidestop' && event.name != 'fillOpacity.slidestop') { os.ui.layer.VectorLayerUICtrl.base(this, 'onSliderStop', callback, key, event, value); return; @@ -505,42 +497,19 @@ os.ui.layer.VectorLayerUICtrl.prototype.onSliderStop = function(callback, key, e event.stopPropagation(); - if (event.name == 'fillOpacity.slidestop') { - var fn = - /** - * @param {os.layer.ILayer} layer - * @return {os.command.ICommand} - */ - function(layer) { - return new os.command.VectorLayerOpacity( - layer.getId(), value, null, os.command.style.ColorChangeType.FILL); - }; - - this.createCommand(fn); - } else if (this.scope['fillOpacity'] !== undefined && this.scope['opacity'] == this.scope['fillOpacity']) { - var fn2 = - /** - * @param {os.layer.ILayer} layer - * @return {?os.command.ICommand} - */ - function(layer) { - return new os.command.VectorLayerOpacity(layer.getId(), value); - }; + var changeType = event.name == 'fillOpacity.slidestop' ? + os.command.style.ColorChangeType.FILL : os.command.style.ColorChangeType.STROKE; - this.createCommand(fn2); - } else { - var fn3 = - /** - * @param {os.layer.ILayer} layer - * @return {?os.command.ICommand} - */ - function(layer) { - return new os.command.VectorLayerOpacity( - layer.getId(), value, null, os.command.style.ColorChangeType.STROKE); - }; + var fn = + /** + * @param {os.layer.ILayer} layer + * @return {os.command.ICommand} + */ + function(layer) { + return new os.command.VectorLayerOpacity(layer.getId(), value, null, changeType); + }; - this.createCommand(fn3); - } + this.createCommand(fn); }; diff --git a/src/plugin/file/kml/kmlnodelayerui.js b/src/plugin/file/kml/kmlnodelayerui.js index 7ddc67eca..fa2e2b163 100644 --- a/src/plugin/file/kml/kmlnodelayerui.js +++ b/src/plugin/file/kml/kmlnodelayerui.js @@ -527,13 +527,7 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.getLockable = function() { */ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onOpacityValueChange = function(event, value) { event.stopPropagation(); - - // If we have a fill opacity and it is already the same as the stroke opacity, keep them the same - if (this.scope['fillOpacity'] !== undefined && this.scope['opacity'] == this.scope['fillOpacity']) { - this.scope['fillOpacity'] = value; - } - - this.scope['opacity'] = value; // do not set this on the config - the command takes care of that + this.scope['opacity'] = value; }; @@ -546,7 +540,6 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onOpacityValueChange = function(eve */ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onFillOpacityValueChange = function(event, value) { event.stopPropagation(); - this.scope['fillOpacity'] = value; }; @@ -807,33 +800,18 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onCenterShapeChange = function(even plugin.file.kml.KMLNodeLayerUICtrl.prototype.onOpacityChange = function(event, value) { event.stopPropagation(); - if (value) { - if (this.scope['fillOpacity'] !== undefined && this.scope['opacity'] == this.scope['fillOpacity']) { - var fn = - /** - * @param {string} layerId - * @param {string} featureId - * @return {os.command.ICommand} - */ - function(layerId, featureId) { - return new os.command.FeatureOpacity(layerId, featureId, value); - }; - - this.createFeatureCommand(fn); - } else { - var fn2 = - /** - * @param {string} layerId - * @param {string} featureId - * @return {os.command.ICommand} - */ - function(layerId, featureId) { - return new os.command.FeatureOpacity(layerId, featureId, value, null, - os.command.style.ColorChangeType.STROKE); - }; + if (value != null) { + var fn = + /** + * @param {string} layerId + * @param {string} featureId + * @return {os.command.ICommand} + */ + function(layerId, featureId) { + return new os.command.FeatureOpacity(layerId, featureId, value, null, os.command.style.ColorChangeType.STROKE); + }; - this.createFeatureCommand(fn2); - } + this.createFeatureCommand(fn); } }; @@ -848,17 +826,19 @@ plugin.file.kml.KMLNodeLayerUICtrl.prototype.onOpacityChange = function(event, v plugin.file.kml.KMLNodeLayerUICtrl.prototype.onFillOpacityChange = function(event, value) { event.stopPropagation(); - var fn = - /** - * @param {string} layerId - * @param {string} featureId - * @return {os.command.ICommand} - */ - function(layerId, featureId) { - return new os.command.FeatureOpacity(layerId, featureId, value, null, os.command.style.ColorChangeType.FILL); - }; + if (value != null) { + var fn = + /** + * @param {string} layerId + * @param {string} featureId + * @return {os.command.ICommand} + */ + function(layerId, featureId) { + return new os.command.FeatureOpacity(layerId, featureId, value, null, os.command.style.ColorChangeType.FILL); + }; - this.createFeatureCommand(fn); + this.createFeatureCommand(fn); + } }; From cfaef24effcac483f102d7e03afa02456de562ed Mon Sep 17 00:00:00 2001 From: Kevin Schmidt Date: Fri, 16 Aug 2019 19:19:55 -0600 Subject: [PATCH 21/28] fix(color): fixed an error when the color picker was given an array Also resolved the issue in the feature color command, which was setting the label color to an array. --- src/os/command/feature/featurecolorcmd.js | 4 ++-- src/os/ui/color/colorpicker.js | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/os/command/feature/featurecolorcmd.js b/src/os/command/feature/featurecolorcmd.js index 85110d14a..d9278c674 100644 --- a/src/os/command/feature/featurecolorcmd.js +++ b/src/os/command/feature/featurecolorcmd.js @@ -151,7 +151,7 @@ os.command.FeatureColor.prototype.applyValue = function(configs, value) { } if (this.oldValue == this.getLabelValue()) { - this.applyLabelValue(configs, value); + this.applyLabelValue(configs, color); } break; case os.command.style.ColorChangeType.COMBINED: @@ -161,7 +161,7 @@ os.command.FeatureColor.prototype.applyValue = function(configs, value) { } if (this.oldValue == this.getLabelValue()) { - this.applyLabelValue(configs, value); + this.applyLabelValue(configs, color); } break; } diff --git a/src/os/ui/color/colorpicker.js b/src/os/ui/color/colorpicker.js index 7f6821073..e069a4e40 100644 --- a/src/os/ui/color/colorpicker.js +++ b/src/os/ui/color/colorpicker.js @@ -1,8 +1,8 @@ goog.provide('os.ui.color.ColorPickerCtrl'); goog.provide('os.ui.color.colorPickerDirective'); -goog.require('goog.color'); -goog.require('goog.color.alpha'); + goog.require('goog.events.EventType'); +goog.require('os.color'); goog.require('os.ui.Module'); goog.require('os.ui.color.ColorPaletteCtrl'); goog.require('os.ui.color.colorPaletteDirective'); @@ -100,10 +100,10 @@ os.ui.color.ColorPickerCtrl = function($scope, $element, $compile) { this['showPopup'] = false; // the control's color value should be undefined when the picker is set to the default color - var color = /** @type {string} */ (this.scope['color']) || undefined; - if (color && color.indexOf('#') !== 0) { - // if color was set to something other than a hex string (rgb() or rgba()), then fix it - color = (color.indexOf('a(') > -1 ? goog.color.alpha.parse(color) : goog.color.parse(color)).hex.substring(0, 7); + var color = /** @type {Array|string} */ (this.scope['color']) || undefined; + if (color) { + // ensure the color is a hex string + color = os.color.toHexString(color); } this.scope['color'] = color; From c2cade29b844e1447861290ce5bad4bfe90feefa Mon Sep 17 00:00:00 2001 From: Kevin Schmidt Date: Mon, 19 Aug 2019 06:18:59 -0600 Subject: [PATCH 22/28] fix(label): revert label color when it matches feature color --- src/os/command/feature/featurecolorcmd.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/os/command/feature/featurecolorcmd.js b/src/os/command/feature/featurecolorcmd.js index d9278c674..229f63817 100644 --- a/src/os/command/feature/featurecolorcmd.js +++ b/src/os/command/feature/featurecolorcmd.js @@ -150,7 +150,9 @@ os.command.FeatureColor.prototype.applyValue = function(configs, value) { } } - if (this.oldValue == this.getLabelValue()) { + // if the label color matches the style color, change it as well + if ((this.state === os.command.State.EXECUTING && this.oldValue == this.getLabelValue()) || + (this.state === os.command.State.REVERTING && this.value == this.getLabelValue())) { this.applyLabelValue(configs, color); } break; @@ -160,7 +162,9 @@ os.command.FeatureColor.prototype.applyValue = function(configs, value) { os.style.setConfigColor(configs[i], color); } - if (this.oldValue == this.getLabelValue()) { + // if the label color matches the style color, change it as well + if ((this.state === os.command.State.EXECUTING && this.oldValue == this.getLabelValue()) || + (this.state === os.command.State.REVERTING && this.value == this.getLabelValue())) { this.applyLabelValue(configs, color); } break; From 8a8c847b2e29181777e1ddda37a04a2662be1e27 Mon Sep 17 00:00:00 2001 From: Kevin Schmidt Date: Mon, 19 Aug 2019 06:33:14 -0600 Subject: [PATCH 23/28] fix(places): persist labels when quick adding places --- src/plugin/places/places.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/plugin/places/places.js b/src/plugin/places/places.js index 243ce2a92..871fc8765 100644 --- a/src/plugin/places/places.js +++ b/src/plugin/places/places.js @@ -381,7 +381,14 @@ plugin.places.addPlace = function(options) { feature.set(os.style.StyleType.FEATURE, [styleConfig]); feature.set(os.style.StyleField.SHAPE, options.shape || os.style.ShapeType.POINT); - feature.set(os.style.StyleField.SHOW_LABELS, !!styleConfig && !!styleConfig['labels']); + + if (styleConfig && styleConfig[os.style.StyleField.LABELS]) { + os.feature.showLabel(feature); + os.ui.FeatureEditCtrl.persistFeatureLabels(feature); + } else { + os.feature.hideLabel(feature); + } + os.style.setFeatureStyle(feature); return parent ? plugin.file.kml.ui.updatePlacemark({ From 7e321987fddaedc524cea54d3ef4d1f76bfb2584 Mon Sep 17 00:00:00 2001 From: Kevin Schmidt Date: Mon, 19 Aug 2019 12:43:40 -0600 Subject: [PATCH 24/28] fix(places): unlink opacity/fill opacity sliders --- src/os/ui/featureedit.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/os/ui/featureedit.js b/src/os/ui/featureedit.js index 2d032b3ec..ba6ad502b 100644 --- a/src/os/ui/featureedit.js +++ b/src/os/ui/featureedit.js @@ -1532,11 +1532,6 @@ os.ui.FeatureEditCtrl.prototype.onLabelColorReset = function(event) { os.ui.FeatureEditCtrl.prototype.onOpacityValueChange = function(event, value) { event.stopPropagation(); - // If we have a fill opacity and it is already the same as the stroke opacity, keep them the same - if (this['fillOpacity'] !== undefined && this['opacity'] == this['fillOpacity']) { - this['fillOpacity'] = value; - } - this['opacity'] = value; }; From d2bce3fb7f46c403f9845c32ad50b9bcabb0ce0b Mon Sep 17 00:00:00 2001 From: Kevin Schmidt Date: Mon, 19 Aug 2019 13:58:21 -0600 Subject: [PATCH 25/28] fix(places): ignore opacity when comparing color/label color --- src/os/command/feature/featurecolorcmd.js | 12 +++++++----- src/os/command/feature/featureopacitycmd.js | 4 +++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/os/command/feature/featurecolorcmd.js b/src/os/command/feature/featurecolorcmd.js index 229f63817..94259df53 100644 --- a/src/os/command/feature/featurecolorcmd.js +++ b/src/os/command/feature/featurecolorcmd.js @@ -118,7 +118,7 @@ os.command.FeatureColor.prototype.getOldValue = function() { /** * Gets the old label color * - * @return {Array|string|undefined} + * @return {Array|string} */ os.command.FeatureColor.prototype.getLabelValue = function() { var feature = /** @type {ol.Feature} */ (this.getFeature()); @@ -133,6 +133,10 @@ os.command.FeatureColor.prototype.getLabelValue = function() { os.command.FeatureColor.prototype.applyValue = function(configs, value) { var color = os.style.toRgbaString(/** @type {string} */ (value)); + // ignore opacity when comparing the label color to the current color + var labelColor = os.color.toHexString(this.getLabelValue()); + var currentColor = os.color.toHexString(this.state === os.command.State.EXECUTING ? this.oldValue : this.value); + switch (this.changeMode) { case os.command.style.ColorChangeType.FILL: for (var i = 0; i < configs.length; i++) { @@ -151,8 +155,7 @@ os.command.FeatureColor.prototype.applyValue = function(configs, value) { } // if the label color matches the style color, change it as well - if ((this.state === os.command.State.EXECUTING && this.oldValue == this.getLabelValue()) || - (this.state === os.command.State.REVERTING && this.value == this.getLabelValue())) { + if (labelColor == currentColor) { this.applyLabelValue(configs, color); } break; @@ -163,8 +166,7 @@ os.command.FeatureColor.prototype.applyValue = function(configs, value) { } // if the label color matches the style color, change it as well - if ((this.state === os.command.State.EXECUTING && this.oldValue == this.getLabelValue()) || - (this.state === os.command.State.REVERTING && this.value == this.getLabelValue())) { + if (labelColor == currentColor) { this.applyLabelValue(configs, color); } break; diff --git a/src/os/command/feature/featureopacitycmd.js b/src/os/command/feature/featureopacitycmd.js index 9a4defdf4..b25783fe7 100644 --- a/src/os/command/feature/featureopacitycmd.js +++ b/src/os/command/feature/featureopacitycmd.js @@ -113,11 +113,13 @@ os.command.FeatureOpacity.prototype.applyValue = function(configs, value) { os.style.getConfigColor(configs[i], true); if (color) { + var fillColor = os.style.getConfigColor(configs[i], true, os.style.StyleField.FILL); + color[3] = value; colorValue = os.style.toRgbaString(color); os.style.setConfigColor(configs[i], colorValue); - var fillColor = os.style.getConfigColor(configs[i], true, os.style.StyleField.FILL); + // preserve the original fill color when changing the stroke if (fillColor) { os.style.setFillColor(configs[i], fillColor); } From 483da545f396eacc53af394595e5d5708659aff4 Mon Sep 17 00:00:00 2001 From: Kevin Schmidt Date: Mon, 19 Aug 2019 13:58:21 -0600 Subject: [PATCH 26/28] fix(opacity): revert to using layer opacity Changing layer opacity at the config level has significant performance implications, in that it creates new style objects for each opacity value. It also prevents the layer opacity control from affecting KML layers because the layer config is ignored. --- src/os/command/feature/featurecolorcmd.js | 36 ++-- src/os/command/feature/featureopacitycmd.js | 46 ++++- src/os/command/vectorlayercolorcmd.js | 112 +++++------- src/os/command/vectorlayerfillopacitycmd.js | 53 ++++++ src/os/command/vectorlayeropacitycmd.js | 169 ----------------- src/os/layer/vector.js | 33 ++-- src/os/state/v4/baselayerstate.js | 23 ++- src/os/style/style.js | 4 +- src/os/ui/layer/vectorlayerui.js | 189 +++++++------------- src/plugin/file/kml/kmlfield.js | 1 - src/plugin/places/places.js | 1 - 11 files changed, 247 insertions(+), 420 deletions(-) create mode 100644 src/os/command/vectorlayerfillopacitycmd.js delete mode 100644 src/os/command/vectorlayeropacitycmd.js diff --git a/src/os/command/feature/featurecolorcmd.js b/src/os/command/feature/featurecolorcmd.js index 94259df53..402b9feb0 100644 --- a/src/os/command/feature/featurecolorcmd.js +++ b/src/os/command/feature/featurecolorcmd.js @@ -34,18 +34,18 @@ os.command.FeatureColor = function(layerId, featureId, color, opt_oldColor, opt_ case os.command.style.ColorChangeType.FILL: this.title = 'Change Feature Fill Color'; this.metricKey = os.metrics.Layer.FEATURE_FILL_COLOR; - this.defaultColor = os.command.FeatureColor.DEFAULT_FILL_COLOR; + this.defaultColor = os.style.DEFAULT_FILL_COLOR; break; case os.command.style.ColorChangeType.STROKE: this.title = 'Change Feature Color'; this.metricKey = os.metrics.Layer.FEATURE_COLOR; - this.defaultColor = os.command.FeatureColor.DEFAULT_COLOR; + this.defaultColor = os.style.DEFAULT_LAYER_COLOR; break; case os.command.style.ColorChangeType.COMBINED: default: this.title = 'Change Feature Color'; this.metricKey = os.metrics.Layer.FEATURE_COLOR; - this.defaultColor = os.command.FeatureColor.DEFAULT_COLOR; + this.defaultColor = os.style.DEFAULT_LAYER_COLOR; break; } @@ -54,7 +54,7 @@ os.command.FeatureColor = function(layerId, featureId, color, opt_oldColor, opt_ var config = /** @type {Object|undefined} */ (feature.get(os.style.StyleType.FEATURE)); if (config) { - if (goog.isArray(config)) { + if (Array.isArray(config)) { config = config[0]; } var configColor = /** @type {Array|string|undefined} */ (os.style.getConfigColor(config)); @@ -70,27 +70,13 @@ os.command.FeatureColor = function(layerId, featureId, color, opt_oldColor, opt_ goog.inherits(os.command.FeatureColor, os.command.AbstractFeatureStyle); -/** - * @type {string} - * @const - */ -os.command.FeatureColor.DEFAULT_COLOR = 'rgba(255,255,255,1)'; - - -/** - * @type {string} - * @const - */ -os.command.FeatureColor.DEFAULT_FILL_COLOR = 'rgba(255,255,255,0)'; - - /** * @inheritDoc */ os.command.FeatureColor.prototype.getOldValue = function() { var feature = /** @type {ol.Feature} */ (this.getFeature()); var config = /** @type {Array|Object|undefined} */ (this.getFeatureConfigs(feature)); - if (goog.isArray(config)) { + if (Array.isArray(config)) { config = config[0]; } @@ -135,7 +121,8 @@ os.command.FeatureColor.prototype.applyValue = function(configs, value) { // ignore opacity when comparing the label color to the current color var labelColor = os.color.toHexString(this.getLabelValue()); - var currentColor = os.color.toHexString(this.state === os.command.State.EXECUTING ? this.oldValue : this.value); + var currentColor = this.state === os.command.State.EXECUTING ? this.oldValue : this.value; + var currentHexColor = currentColor ? os.color.toHexString(currentColor) : null; switch (this.changeMode) { case os.command.style.ColorChangeType.FILL: @@ -145,17 +132,18 @@ os.command.FeatureColor.prototype.applyValue = function(configs, value) { break; case os.command.style.ColorChangeType.STROKE: for (var i = 0; i < configs.length; i++) { - var fillColor = os.style.getConfigColor(configs[i], true, os.style.StyleField.FILL); + var fillColor = os.style.getConfigColor(configs[i], false, os.style.StyleField.FILL); os.style.setConfigColor(configs[i], color); + // preserve the original fill color when changing the stroke if (fillColor) { - os.style.setFillColor(configs[i], fillColor); + os.style.setFillColor(configs[i], os.style.toRgbaString(fillColor)); } } // if the label color matches the style color, change it as well - if (labelColor == currentColor) { + if (labelColor == currentHexColor) { this.applyLabelValue(configs, color); } break; @@ -166,7 +154,7 @@ os.command.FeatureColor.prototype.applyValue = function(configs, value) { } // if the label color matches the style color, change it as well - if (labelColor == currentColor) { + if (labelColor == currentHexColor) { this.applyLabelValue(configs, color); } break; diff --git a/src/os/command/feature/featureopacitycmd.js b/src/os/command/feature/featureopacitycmd.js index b25783fe7..a2455cdfc 100644 --- a/src/os/command/feature/featureopacitycmd.js +++ b/src/os/command/feature/featureopacitycmd.js @@ -48,6 +48,10 @@ os.command.FeatureOpacity = function(layerId, featureId, opacity, opt_oldOpacity this.metricKey = os.metrics.Layer.FEATURE_OPACITY; break; } + + if (this.value == null) { + this.value = os.style.DEFAULT_FILL_ALPHA; + } }; goog.inherits(os.command.FeatureOpacity, os.command.AbstractFeatureStyle); @@ -91,7 +95,6 @@ os.command.FeatureOpacity.prototype.getOldValue = function() { */ os.command.FeatureOpacity.prototype.applyValue = function(configs, value) { var color; - var colorValue; var i; switch (this.changeMode) { @@ -102,8 +105,7 @@ os.command.FeatureOpacity.prototype.applyValue = function(configs, value) { if (color) { color[3] = value; - colorValue = os.style.toRgbaString(color); - os.style.setFillColor(configs[i], colorValue); + os.style.setFillColor(configs[i], os.style.toRgbaString(color)); } } break; @@ -113,11 +115,12 @@ os.command.FeatureOpacity.prototype.applyValue = function(configs, value) { os.style.getConfigColor(configs[i], true); if (color) { - var fillColor = os.style.getConfigColor(configs[i], true, os.style.StyleField.FILL); + var fillColor = os.style.getConfigColor(configs[i], false, os.style.StyleField.FILL); color[3] = value; - colorValue = os.style.toRgbaString(color); - os.style.setConfigColor(configs[i], colorValue); + + var colorStr = os.style.toRgbaString(color); + os.style.setConfigColor(configs[i], colorStr); // preserve the original fill color when changing the stroke if (fillColor) { @@ -125,6 +128,7 @@ os.command.FeatureOpacity.prototype.applyValue = function(configs, value) { } } } + this.updateLabelOpacity(configs, value); break; case os.command.style.ColorChangeType.COMBINED: default: @@ -133,10 +137,12 @@ os.command.FeatureOpacity.prototype.applyValue = function(configs, value) { if (color) { color[3] = value; - colorValue = os.style.toRgbaString(color); - os.style.setConfigColor(configs[i], colorValue); + + var colorStr = os.style.toRgbaString(color); + os.style.setConfigColor(configs[i], colorStr); } } + this.updateLabelOpacity(configs, value); break; } @@ -144,6 +150,30 @@ os.command.FeatureOpacity.prototype.applyValue = function(configs, value) { }; +/** + * Set the label color + * + * @param {Object} configs The style config + * @param {number} value The opacity value. + */ +os.command.FeatureOpacity.prototype.updateLabelOpacity = function(configs, value) { + var feature = /** @type {ol.Feature} */ (this.getFeature()); + if (feature) { + var labelColor = /** @type {Array|string|undefined} */ (feature.get(os.style.StyleField.LABEL_COLOR)) || + os.style.DEFAULT_LAYER_COLOR; + labelColor = os.color.toRgbArray(labelColor); + labelColor[3] = value; + + var labelColorStr = os.style.toRgbaString(labelColor); + feature.set(os.style.StyleField.LABEL_COLOR, labelColorStr); + + for (var i = 0; i < configs.length; i++) { + configs[i][os.style.StyleField.LABEL_COLOR] = labelColorStr; + } + } +}; + + /** * @inheritDoc */ diff --git a/src/os/command/vectorlayercolorcmd.js b/src/os/command/vectorlayercolorcmd.js index 4712fa699..14b3dca5d 100644 --- a/src/os/command/vectorlayercolorcmd.js +++ b/src/os/command/vectorlayercolorcmd.js @@ -21,38 +21,41 @@ goog.require('os.source.PropertyChange'); os.command.VectorLayerColor = function(layerId, color, opt_oldColor, opt_changeMode) { /** * The color change mode. Determines how the config color is set. - * @type {os.command.style.ColorChangeType} + * @type {os.command.style.ColorChangeType|undefined} * @protected */ - this.changeMode = opt_changeMode || os.command.style.ColorChangeType.COMBINED; + this.changeMode = opt_changeMode; // intentionally called after changeMode is set so getOldValue has the correct value os.command.VectorLayerColor.base(this, 'constructor', layerId, color, opt_oldColor); - switch (this.changeMode) { - case os.command.style.ColorChangeType.FILL: - this.title = 'Change Fill Color'; - this.metricKey = os.metrics.Layer.VECTOR_FILL_COLOR; - this.defaultColor = os.style.DEFAULT_FILL_COLOR; - break; - case os.command.style.ColorChangeType.STROKE: - this.title = 'Change Color'; - this.metricKey = os.metrics.Layer.VECTOR_COLOR; - this.defaultColor = os.style.DEFAULT_LAYER_COLOR; - break; - case os.command.style.ColorChangeType.COMBINED: - default: - this.title = 'Change Color'; - this.metricKey = os.metrics.Layer.VECTOR_COLOR; - this.defaultColor = os.style.DEFAULT_LAYER_COLOR; - break; + if (this.changeMode === os.command.style.ColorChangeType.FILL) { + this.title = 'Change Layer Fill Color'; + this.metricKey = os.metrics.Layer.VECTOR_FILL_COLOR; + } else { + this.title = 'Change Layer Color'; + this.metricKey = os.metrics.Layer.VECTOR_COLOR; } if (!color) { var layer = /** @type {os.layer.Vector} */ (os.MapContainer.getInstance().getLayer(this.layerId)); if (layer) { var options = layer.getLayerOptions(); - color = /** @type {string} */ (options && options['baseColor'] || this.defaultColor); + color = /** @type {string} */ (options && options['baseColor'] || os.style.DEFAULT_LAYER_COLOR); + } else { + color = os.style.DEFAULT_LAYER_COLOR; + } + } + + // when changing the fill, preserve the old alpha value + if (this.changeMode === os.command.style.ColorChangeType.FILL) { + var config = os.style.StyleManager.getInstance().getLayerConfig(this.layerId); + if (config) { + var currentFill = os.style.getConfigColor(config, true, os.style.StyleField.FILL); + var currentFillAlpha = currentFill && currentFill.length === 4 ? currentFill[3] : os.style.DEFAULT_FILL_ALPHA; + + color = os.color.toRgbArray(color); + color[3] = currentFillAlpha; } } @@ -67,23 +70,12 @@ goog.inherits(os.command.VectorLayerColor, os.command.AbstractVectorStyle); */ os.command.VectorLayerColor.prototype.getOldValue = function() { var config = os.style.StyleManager.getInstance().getLayerConfig(this.layerId); - var ret; - if (config) { - switch (this.changeMode) { - case os.command.style.ColorChangeType.FILL: - ret = os.style.getConfigColor(config, false, os.style.StyleField.FILL); - break; - case os.command.style.ColorChangeType.STROKE: - ret = os.style.getConfigColor(config, false, os.style.StyleField.STROKE); - break; - case os.command.style.ColorChangeType.COMBINED: - default: - ret = os.style.getConfigColor(config); - break; - } + var ret; + if (this.changeMode === os.command.style.ColorChangeType.FILL) { + ret = config ? os.style.getConfigColor(config, false, os.style.StyleField.FILL) : os.style.DEFAULT_FILL_COLOR; } else { - ret = this.defaultColor; + ret = config ? os.style.getConfigColor(config) : os.style.DEFAULT_LAYER_COLOR; } return ret; @@ -94,42 +86,20 @@ os.command.VectorLayerColor.prototype.getOldValue = function() { * @inheritDoc */ os.command.VectorLayerColor.prototype.applyValue = function(config, value) { - var color = os.style.toRgbaString(/** @type {string} */ (value)); - - switch (this.changeMode) { - case os.command.style.ColorChangeType.FILL: - os.style.setFillColor(config, color); - - // Make sure the fill color and opacity are updated as well - if (config['fillColor']) { - config['fillColor'] = color; - } - break; - case os.command.style.ColorChangeType.STROKE: - os.style.setConfigColor(config, color); - - if (config['fillColor']) { - os.style.setFillColor(config, config['fillColor']); - } - - os.ui.adjustIconSet(this.layerId, color); - break; - case os.command.style.ColorChangeType.COMBINED: - default: - os.style.setConfigColor(config, color); - - // Make sure the fill color and opacity are updated as well - if (config['fillColor']) { - config['fillColor'] = color; - } - if (config['fillOpacity'] !== undefined) { - var colorArray = os.color.toRgbArray(value); - config['fillOpacity'] = colorArray[3]; - } - - os.ui.adjustIconSet(this.layerId, color); - - break; + if (this.changeMode === os.command.style.ColorChangeType.FILL) { + os.style.setFillColor(config, value); + } else { + // preserve the original fill color so the opacity isn't changed + var fillColor = os.style.getConfigColor(config, false, os.style.StyleField.FILL); + + // update the config color + os.style.setConfigColor(config, value); + + // restore the fill color + os.style.setFillColor(config, fillColor); + + // update the layer icons to reflect the color change + os.ui.adjustIconSet(this.layerId, value); } os.command.VectorLayerColor.base(this, 'applyValue', config, value); diff --git a/src/os/command/vectorlayerfillopacitycmd.js b/src/os/command/vectorlayerfillopacitycmd.js new file mode 100644 index 000000000..d6e055b57 --- /dev/null +++ b/src/os/command/vectorlayerfillopacitycmd.js @@ -0,0 +1,53 @@ +goog.provide('os.command.VectorLayerFillOpacity'); + +goog.require('goog.asserts'); +goog.require('os.command.AbstractVectorStyle'); +goog.require('os.metrics'); + + +/** + * Changes the fill opacity of a vector layer. + * @param {string} layerId The layer id. + * @param {number} opacity The new fill opacity value. + * @param {number|null=} opt_oldOpacity The old fill opacity value. + * @extends {os.command.AbstractVectorStyle} + * @constructor + */ +os.command.VectorLayerFillOpacity = function(layerId, opacity, opt_oldOpacity) { + os.command.VectorLayerFillOpacity.base(this, 'constructor', layerId, opacity, opt_oldOpacity); + this.title = 'Change Layer Fill Opacity'; + this.metricKey = os.metrics.Layer.VECTOR_FILL_OPACITY; + + if (this.value == null) { + this.value = os.style.DEFAULT_FILL_ALPHA; + } +}; +goog.inherits(os.command.VectorLayerFillOpacity, os.command.AbstractVectorStyle); + + +/** + * @inheritDoc + */ +os.command.VectorLayerFillOpacity.prototype.getOldValue = function() { + var config = os.style.StyleManager.getInstance().getLayerConfig(this.layerId); + var color = os.style.getConfigColor(config, true, os.style.StyleField.FILL); + return color && color.length === 4 ? color[3] : os.style.DEFAULT_FILL_ALPHA; +}; + + +/** + * @inheritDoc + */ +os.command.VectorLayerFillOpacity.prototype.applyValue = function(config, value) { + var color = os.style.getConfigColor(config, true, os.style.StyleField.FILL) || + os.style.getConfigColor(config, true); + + if (color) { + color[3] = value; + + var colorString = os.style.toRgbaString(color); + os.style.setFillColor(config, colorString); + } + + os.command.VectorLayerFillOpacity.base(this, 'applyValue', config, value); +}; diff --git a/src/os/command/vectorlayeropacitycmd.js b/src/os/command/vectorlayeropacitycmd.js deleted file mode 100644 index 90045420e..000000000 --- a/src/os/command/vectorlayeropacitycmd.js +++ /dev/null @@ -1,169 +0,0 @@ -goog.provide('os.command.VectorLayerOpacity'); - -goog.require('goog.asserts'); -goog.require('os.command.AbstractVectorStyle'); -goog.require('os.command.style'); -goog.require('os.events.PropertyChangeEvent'); -goog.require('os.metrics'); -goog.require('os.source.PropertyChange'); - - - -/** - * Changes the color of a layer - * - * @extends {os.command.AbstractVectorStyle} - * @param {string} layerId - * @param {number} opacity - * @param {number|null=} opt_oldOpacity - * @param {os.command.style.ColorChangeType=} opt_changeMode - * @constructor - */ -os.command.VectorLayerOpacity = function(layerId, opacity, opt_oldOpacity, opt_changeMode) { - goog.asserts.assert(opacity != null, 'opacity must be defined'); - - /** - * The opacity change mode. Determines how the config opacity is set. - * @type {os.command.style.ColorChangeType} - * @protected - */ - this.changeMode = opt_changeMode || os.command.style.ColorChangeType.COMBINED; - - // intentionally called after changeMode is set so getOldValue has the correct value - os.command.VectorLayerOpacity.base(this, 'constructor', layerId, opacity, opt_oldOpacity); - - switch (this.changeMode) { - case os.command.style.ColorChangeType.FILL: - this.title = 'Change Fill Opacity'; - this.metricKey = os.metrics.Layer.VECTOR_FILL_OPACITY; - break; - case os.command.style.ColorChangeType.STROKE: - this.title = 'Change Opacity'; - this.metricKey = os.metrics.Layer.VECTOR_OPACITY; - break; - case os.command.style.ColorChangeType.COMBINED: - default: - this.title = 'Change Opacity'; - this.metricKey = os.metrics.Layer.VECTOR_OPACITY; - break; - } -}; -goog.inherits(os.command.VectorLayerOpacity, os.command.AbstractVectorStyle); - - -/** - * @inheritDoc - */ -os.command.VectorLayerOpacity.prototype.getOldValue = function() { - var config = os.style.StyleManager.getInstance().getLayerConfig(this.layerId); - var ret; - - if (config) { - var color; - switch (this.changeMode) { - case os.command.style.ColorChangeType.FILL: - color = os.style.getConfigColor(config, true, os.style.StyleField.FILL); - ret = color && color.length === 4 ? color[3] : os.style.DEFAULT_FILL_ALPHA; - break; - case os.command.style.ColorChangeType.STROKE: - color = os.style.getConfigColor(config, true, os.style.StyleField.STROKE); - ret = color && color.length === 4 ? color[3] : os.style.DEFAULT_ALPHA; - break; - case os.command.style.ColorChangeType.COMBINED: - default: - color = os.style.getConfigColor(config, true); - ret = color && color.length === 4 ? color[3] : os.style.DEFAULT_ALPHA; - break; - } - } - - return ret; -}; - - -/** - * @inheritDoc - */ -os.command.VectorLayerOpacity.prototype.applyValue = function(config, value) { - var color; - var colorString; - - switch (this.changeMode) { - case os.command.style.ColorChangeType.FILL: - color = os.style.getConfigColor(config, true, os.style.StyleField.FILL) || - os.style.getConfigColor(config, true); - - if (color) { - color[3] = value; - colorString = os.style.toRgbaString(color); - - os.style.setFillColor(config, colorString); - - // Make sure the fill color and opacity are updated as well - if (config['fillColor']) { - config['fillColor'] = colorString; - } - if (config['fillOpacity'] !== undefined) { - config['fillOpacity'] = value; - } - } - break; - case os.command.style.ColorChangeType.STROKE: - color = os.style.getConfigColor(config, true, os.style.StyleField.STROKE) || - os.style.getConfigColor(config, true); - - if (color) { - color[3] = value; - colorString = os.style.toRgbaString(color); - - os.style.setConfigColor(config, color); - - if (config['fillColor']) { - os.style.setFillColor(config, config['fillColor']); - } - - os.ui.adjustIconSet(this.layerId, color); - } - break; - case os.command.style.ColorChangeType.COMBINED: - default: - color = os.style.getConfigColor(config, true); - - if (color) { - color[3] = value; - colorString = os.style.toRgbaString(color); - - os.style.setConfigColor(config, colorString); - - // Make sure the fill color and opacity are updated as well - if (config['fillColor']) { - config['fillColor'] = colorString; - } - if (config['fillOpacity'] !== undefined) { - config['fillOpacity'] = value; - } - - os.ui.adjustIconSet(this.layerId, color); - } - break; - } - - os.command.VectorLayerOpacity.base(this, 'applyValue', config, value); -}; - - -/** - * @inheritDoc - */ -os.command.VectorLayerOpacity.prototype.finish = function(config) { - // dispatch the color change event on the source for the histogram - var source = os.osDataManager.getSource(this.layerId); - source.dispatchEvent(new os.events.PropertyChangeEvent(os.source.PropertyChange.COLOR, this.value)); - - if (source instanceof os.source.Vector) { - // a color change on the layer should clear any color model on the source - source.setColorModel(null); - } - - os.command.VectorLayerOpacity.base(this, 'finish', config); -}; diff --git a/src/os/layer/vector.js b/src/os/layer/vector.js index 5f5e13221..d485c1964 100644 --- a/src/os/layer/vector.js +++ b/src/os/layer/vector.js @@ -1147,6 +1147,7 @@ os.layer.Vector.prototype.persist = function(opt_to) { opt_to[os.style.StyleField.ARROW_SIZE] = config[os.style.StyleField.ARROW_SIZE]; opt_to[os.style.StyleField.ARROW_UNITS] = config[os.style.StyleField.ARROW_UNITS]; opt_to[os.style.StyleField.COLOR] = os.style.getConfigColor(config); + opt_to[os.style.StyleField.FILL_COLOR] = os.style.getConfigColor(config, false, os.style.StyleField.FILL); opt_to[os.style.StyleField.REPLACE_STYLE] = config[os.style.StyleField.REPLACE_STYLE]; opt_to[os.style.StyleField.SIZE] = os.style.getConfigSize(config); opt_to[os.style.StyleField.ICON] = os.style.getConfigIcon(config); @@ -1165,8 +1166,6 @@ os.layer.Vector.prototype.persist = function(opt_to) { opt_to[os.style.StyleField.LOB_BEARING_COLUMN] = config[os.style.StyleField.LOB_BEARING_COLUMN]; opt_to[os.style.StyleField.LOB_BEARING_ERROR] = config[os.style.StyleField.LOB_BEARING_ERROR]; opt_to[os.style.StyleField.LOB_BEARING_ERROR_COLUMN] = config[os.style.StyleField.LOB_BEARING_ERROR_COLUMN]; - opt_to[os.style.StyleField.FILL_COLOR] = os.style.getConfigColor(config, false, os.style.StyleField.FILL); - opt_to[os.style.StyleField.FILL_OPACITY] = config[os.style.StyleField.FILL_OPACITY]; opt_to[os.style.StyleField.ROTATION_COLUMN] = config[os.style.StyleField.ROTATION_COLUMN]; opt_to[os.style.StyleField.SHOW_ROTATION] = config[os.style.StyleField.SHOW_ROTATION]; opt_to[os.style.StyleField.SHOW_ARROW] = config[os.style.StyleField.SHOW_ARROW]; @@ -1240,17 +1239,27 @@ os.layer.Vector.prototype.restore = function(config) { this.setMinResolution(config['minResolution'] || this.getMinResolution()); this.setMaxResolution(config['maxResolution'] || this.getMaxResolution()); - if (config[os.style.StyleField.COLOR] != null) { - os.style.setConfigColor(styleConf, os.style.toRgbaString(config[os.style.StyleField.COLOR])); + var color = config[os.style.StyleField.COLOR]; + if (color) { + os.style.setConfigColor(styleConf, os.style.toRgbaString(color)); + } + + var fillColor = config[os.style.StyleField.FILL_COLOR]; - if (config[os.style.StyleField.FILL_COLOR] != null) { - var fillString = os.style.toRgbaString(config[os.style.StyleField.FILL_COLOR]); - os.style.setFillColor(styleConf, fillString); - } else { - var fillArr = os.color.toRgbArray(config[os.style.StyleField.COLOR]); - fillArr[3] = os.style.DEFAULT_FILL_ALPHA; - os.style.setFillColor(styleConf, os.style.toRgbaString(fillArr)); + // if fill color is not defined, use the base color with default fill opacity + if (!fillColor && color) { + fillColor = os.color.toRgbArray(color); + fillColor[3] = os.style.DEFAULT_FILL_ALPHA; + } + + if (fillColor) { + // if a fill opacity is defined, override it in the color + if (config[os.style.StyleField.FILL_OPACITY] != null) { + fillColor = os.color.toRgbArray(fillColor); + fillColor[3] = config[os.style.StyleField.FILL_OPACITY]; } + + os.style.setFillColor(styleConf, os.style.toRgbaString(fillColor)); } if (config[os.style.StyleField.REPLACE_STYLE] != null) { @@ -1295,8 +1304,6 @@ os.layer.Vector.prototype.restore = function(config) { styleConf[os.style.StyleField.ARROW_SIZE] = config[os.style.StyleField.ARROW_SIZE] || os.style.DEFAULT_ARROW_SIZE; styleConf[os.style.StyleField.ARROW_UNITS] = config[os.style.StyleField.ARROW_UNITS] || os.style.DEFAULT_UNITS; - styleConf[os.style.StyleField.FILL_COLOR] = config[os.style.StyleField.FILL_COLOR] || os.style.DEFAULT_FILL_COLOR; - styleConf[os.style.StyleField.FILL_OPACITY] = config[os.style.StyleField.FILL_OPACITY] || os.style.DEFAULT_FILL_ALPHA; styleConf[os.style.StyleField.LOB_COLUMN_LENGTH] = config[os.style.StyleField.LOB_COLUMN_LENGTH] || os.style.DEFAULT_LOB_LENGTH; styleConf[os.style.StyleField.LOB_LENGTH] = config[os.style.StyleField.LOB_LENGTH] || os.style.DEFAULT_LOB_LENGTH; diff --git a/src/os/state/v4/baselayerstate.js b/src/os/state/v4/baselayerstate.js index 86b20bddb..1d0ddbc2d 100644 --- a/src/os/state/v4/baselayerstate.js +++ b/src/os/state/v4/baselayerstate.js @@ -475,8 +475,13 @@ os.state.v4.BaseLayerState.prototype.configKeyToXML = function(layerConfig, type case os.style.StyleField.FILL_COLOR: if (bfs) { // hex string without the leading hash - var fillColor = os.color.toServerString(/** @type {string} */ (value)); - os.xml.appendElement(os.state.v4.LayerTag.FILL_COLOR, bfs, fillColor); + var xmlColor = os.color.toServerString(/** @type {string} */ (value)); + os.xml.appendElement(os.state.v4.LayerTag.FILL_COLOR, bfs, xmlColor); + + // extract opacity from the color string + var colorArr = os.color.toRgbArray(/** @type {string} */ (value)); + var fillOpacity = colorArr.length == 4 ? colorArr[3] : os.style.DEFAULT_FILL_ALPHA; + os.xml.appendElement(os.state.v4.LayerTag.FILL_OPACITY, bfs, fillOpacity); } else { // tile layer this.defaultConfigToXML(key, value, layerEl); @@ -961,6 +966,20 @@ os.state.v4.BaseLayerState.prototype.xmlToConfigKey = function(node, child, name options['size'] = goog.string.isNumeric(styleVal) ? Number(styleVal) / 2 : os.style.DEFAULT_FEATURE_SIZE; break; + case os.state.v4.LayerTag.FILL_COLOR: + try { + styleVal = os.color.padHexColor(styleVal, '#'); + options[os.style.StyleField.FILL_COLOR] = os.style.toRgbaString(styleVal); + } catch (e) { + } + break; + case os.state.v4.LayerTag.FILL_OPACITY: + var fillOpacity = Number(styleVal); + if (isNaN(fillOpacity)) { + fillOpacity = os.style.DEFAULT_FILL_ALPHA; + } + options[os.style.StyleField.FILL_OPACITY] = goog.math.clamp(fillOpacity, 0, 1); + break; case os.state.v4.LayerTag.LABEL_COLUMN: var column = typeof styleVal === 'string' ? goog.string.trim(styleVal) : ''; // Is this the default? diff --git a/src/os/style/style.js b/src/os/style/style.js index 78a348b6d..80978ce25 100644 --- a/src/os/style/style.js +++ b/src/os/style/style.js @@ -643,13 +643,13 @@ os.style.setConfigColor = function(config, color, opt_includeStyleFields) { * Colors are always set as an rgba string to minimize conversion both in opensphere style functions and OL3 rendering functions. * * @param {Object} config - * @param {Array|string|null} color + * @param {Array|string|null|undefined} color */ os.style.setFillColor = function(config, color) { if (config) { if (!color) { // no fill - config['fill'] = null; + config['fill'] = color; } else if (!config['fill']) { // adding fill config['fill'] = { diff --git a/src/os/ui/layer/vectorlayerui.js b/src/os/ui/layer/vectorlayerui.js index 2513dcd44..cd0e1bc22 100644 --- a/src/os/ui/layer/vectorlayerui.js +++ b/src/os/ui/layer/vectorlayerui.js @@ -9,12 +9,12 @@ goog.require('os.command.SequenceCommand'); goog.require('os.command.VectorLayerAutoRefresh'); goog.require('os.command.VectorLayerCenterShape'); goog.require('os.command.VectorLayerColor'); +goog.require('os.command.VectorLayerFillOpacity'); goog.require('os.command.VectorLayerIcon'); goog.require('os.command.VectorLayerLabel'); goog.require('os.command.VectorLayerLabelColor'); goog.require('os.command.VectorLayerLabelSize'); goog.require('os.command.VectorLayerLineDash'); -goog.require('os.command.VectorLayerOpacity'); goog.require('os.command.VectorLayerReplaceStyle'); goog.require('os.command.VectorLayerRotation'); goog.require('os.command.VectorLayerShape'); @@ -329,77 +329,47 @@ os.ui.layer.VectorLayerUICtrl.prototype.reconcileLabelsState_ = function() { * @protected */ os.ui.layer.VectorLayerUICtrl.prototype.onColorChange = function(event, value) { - if (!os.color.isColorString(value) && !goog.isArray(value)) { - return; - } event.stopPropagation(); - // Make sure the value includes the current opacity - var colorValue = os.color.toRgbArray(value); - colorValue[3] = this.scope['opacity']; - - // Determine if we are changing both stroke and fill entirely, or keeping opacities separate, or only affecting stroke - var color = this.scope['color']; - var fillColor = this.scope['fillColor']; - var opacity = this.scope['opacity']; - var fillOpacity = this.scope['fillOpacity']; - - this.scope['color'] = os.style.toRgbaString(colorValue); - - if (color == fillColor && opacity == fillOpacity) { - var fn = - /** - * @param {os.layer.ILayer} layer - * @return {os.command.ICommand} - */ - function(layer) { - return new os.command.VectorLayerColor( - layer.getId(), colorValue, null, os.command.style.ColorChangeType.COMBINED); - }; + var color = this.getColor(); + var fillColor = this.getFillColor() || color; - this.createCommand(fn); - } else if (color == fillColor) { - var strokeArray = colorValue.slice(0, 3); - strokeArray.push(opacity); - var fillArray = colorValue.slice(0, 3); - fillArray.push(fillOpacity); - - // We run these sequentially so that they retain the different opacities - var fn2 = - /** - * @param {os.layer.ILayer} layer - * @return {os.command.ICommand} - */ - function(layer) { - var cmds = []; - - cmds.push(new os.command.VectorLayerColor( - layer.getId(), strokeArray, null, os.command.style.ColorChangeType.STROKE) - ); - cmds.push(new os.command.VectorLayerColor( - layer.getId(), fillArray, null, os.command.style.ColorChangeType.FILL) - ); + // if the color and fill color are the same, change both of them + if (color == fillColor) { + this.createCommand( + /** + * @param {os.layer.ILayer} layer + * @return {os.command.ICommand} + */ + function(layer) { + var cmds = []; - var sequence = new os.command.SequenceCommand(); - sequence.setCommands(cmds); - sequence.title = 'Change Color'; + // We run these sequentially so that they retain the different opacities + cmds.push(new os.command.VectorLayerColor( + layer.getId(), value, null, os.command.style.ColorChangeType.STROKE) + ); + cmds.push(new os.command.VectorLayerColor( + layer.getId(), value, null, os.command.style.ColorChangeType.FILL) + ); - return sequence; - }; + var sequence = new os.command.SequenceCommand(); + sequence.setCommands(cmds); + sequence.title = 'Change Color'; - this.createCommand(fn2); + return sequence; + } + ); } else { - var fn3 = - /** - * @param {os.layer.ILayer} layer - * @return {os.command.ICommand} - */ - function(layer) { - return new os.command.VectorLayerColor( - layer.getId(), colorValue, null, os.command.style.ColorChangeType.STROKE); - }; - - this.createCommand(fn3); + this.createCommand( + /** + * @param {os.layer.ILayer} layer + * @return {os.command.ICommand} + */ + function(layer) { + return new os.command.VectorLayerColor( + layer.getId(), value, null, os.command.style.ColorChangeType.STROKE); + } + ); } }; @@ -413,7 +383,7 @@ os.ui.layer.VectorLayerUICtrl.prototype.onColorReset = function(event) { event.stopPropagation(); // clear the layer color config value - this.onColorChange(event, os.style.DEFAULT_LAYER_COLOR); + this.onColorChange(event, ''); // reset to the layer color this.scope['color'] = this.getColor(); @@ -427,11 +397,13 @@ os.ui.layer.VectorLayerUICtrl.prototype.onColorReset = function(event) { * @protected */ os.ui.layer.VectorLayerUICtrl.prototype.onFillColorChange = function(event, value) { - if (!os.color.isColorString(value) && !goog.isArray(value)) { - return; - } event.stopPropagation(); + // If no value provided, set to the fill color + if (!value) { + value = this.getColor() || os.style.DEFAULT_FILL_COLOR; + } + // Make sure the value includes the current opacity var colorValue = os.color.toRgbArray(value); colorValue[3] = this.scope['fillOpacity']; @@ -460,11 +432,8 @@ os.ui.layer.VectorLayerUICtrl.prototype.onFillColorChange = function(event, valu os.ui.layer.VectorLayerUICtrl.prototype.onFillColorReset = function(event) { event.stopPropagation(); - // clear the layer color config value - this.onFillColorChange(event, os.style.toRgbaString(this.getColor())); - - // reset to the layer color - this.scope['fillColor'] = this.getFillColor(); + // reset to match the base color + this.onFillColorChange(event, ''); }; @@ -472,16 +441,11 @@ os.ui.layer.VectorLayerUICtrl.prototype.onFillColorReset = function(event) { * @override */ os.ui.layer.VectorLayerUICtrl.prototype.onValueChange = function(callback, event, value) { - // If we are not dealing with opacity of fill opacity, let the parent handle this event - if (event.name != 'opacity.slide' && event.name != 'fillOpacity.slide') { - os.ui.layer.VectorLayerUICtrl.base(this, 'onValueChange', callback, event, value); - return; - } - + // If we are not dealing with fill opacity, let the parent handle this event if (event.name == 'fillOpacity.slide') { this.scope['fillOpacity'] = value; } else { - this.scope['opacity'] = value; + os.ui.layer.VectorLayerUICtrl.base(this, 'onValueChange', callback, event, value); } }; @@ -489,27 +453,23 @@ os.ui.layer.VectorLayerUICtrl.prototype.onValueChange = function(callback, event * @inheritDoc */ os.ui.layer.VectorLayerUICtrl.prototype.onSliderStop = function(callback, key, event, value) { - // If we are not dealing with opacity or fill opacity, let the parent handle this event - if (event.name != 'opacity.slidestop' && event.name != 'fillOpacity.slidestop') { - os.ui.layer.VectorLayerUICtrl.base(this, 'onSliderStop', callback, key, event, value); - return; - } - - event.stopPropagation(); + if (event && event.name == 'fillOpacity.slidestop') { + // Fill opacity must be changed at the style level + event.stopPropagation(); - var changeType = event.name == 'fillOpacity.slidestop' ? - os.command.style.ColorChangeType.FILL : os.command.style.ColorChangeType.STROKE; - - var fn = - /** - * @param {os.layer.ILayer} layer - * @return {os.command.ICommand} - */ - function(layer) { - return new os.command.VectorLayerOpacity(layer.getId(), value, null, changeType); - }; + var fn = + /** + * @param {os.layer.ILayer} layer + * @return {os.command.ICommand} + */ + function(layer) { + return new os.command.VectorLayerFillOpacity(layer.getId(), value); + }; - this.createCommand(fn); + this.createCommand(fn); + } else { + os.ui.layer.VectorLayerUICtrl.base(this, 'onSliderStop', callback, key, event, value); + } }; @@ -801,35 +761,6 @@ os.ui.layer.VectorLayerUICtrl.prototype.getFillColor = function() { }; -/** - * @override - */ -os.ui.layer.VectorLayerUICtrl.prototype.getOpacity = function() { - var items = /** @type {Array} */ (this.scope['items']); - var opacity = os.style.DEFAULT_ALPHA; - - if (items) { - for (var i = 0, n = items.length; i < n; i++) { - var layer = items[i].getLayer(); - - if (layer) { - var config = os.style.StyleManager.getInstance().getLayerConfig(items[0].getId()); - - if (config) { - if (goog.isArray(config)) { - config = config[0]; - } - var color = os.style.getConfigColor(config, true, os.style.StyleField.STROKE); - opacity = color[3]; - } - } - } - } - - return opacity; -}; - - /** * Gets the fill opacity from the item(s) * @return {?number} an opacity amount diff --git a/src/plugin/file/kml/kmlfield.js b/src/plugin/file/kml/kmlfield.js index ba6539667..8825c4a36 100644 --- a/src/plugin/file/kml/kmlfield.js +++ b/src/plugin/file/kml/kmlfield.js @@ -59,7 +59,6 @@ plugin.file.kml.SOURCE_FIELDS = [ os.style.StyleField.LABEL_COLOR, os.style.StyleField.LABEL_SIZE, os.style.StyleField.FILL_COLOR, - os.style.StyleField.FILL_OPACITY, os.style.StyleField.SHOW_LABELS ]; diff --git a/src/plugin/places/places.js b/src/plugin/places/places.js index 871fc8765..7cbcaa033 100644 --- a/src/plugin/places/places.js +++ b/src/plugin/places/places.js @@ -68,7 +68,6 @@ plugin.places.ExportFields = [ os.style.StyleField.LABEL_COLOR, os.style.StyleField.LABEL_SIZE, os.style.StyleField.FILL_COLOR, - os.style.StyleField.FILL_OPACITY, os.Fields.ALT, os.Fields.ALT_UNITS, os.data.RecordField.ALTITUDE_MODE, From 60e997eb860b3b4b1cd4ce9ff30f3560d8d85de5 Mon Sep 17 00:00:00 2001 From: Kevin Schmidt Date: Tue, 20 Aug 2019 09:40:06 -0600 Subject: [PATCH 27/28] fix(state): remove fill opacity case Fill opacity is serialized in the fill color case. --- src/os/state/v4/baselayerstate.js | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/os/state/v4/baselayerstate.js b/src/os/state/v4/baselayerstate.js index 1d0ddbc2d..ae827356b 100644 --- a/src/os/state/v4/baselayerstate.js +++ b/src/os/state/v4/baselayerstate.js @@ -510,22 +510,6 @@ os.state.v4.BaseLayerState.prototype.configKeyToXML = function(layerConfig, type os.xml.appendElement(os.state.v4.LayerTag.ALPHA, layerEl, value); } break; - case os.style.StyleField.FILL_OPACITY: - if (bfs) { - value = value != null ? Number(value) : os.style.DEFAULT_FILL_ALPHA; - var opacity = Math.round(value * 255); - var fillOpacityElement = bfs.querySelector(os.state.v4.LayerTag.FILL_OPACITY); - if (fillOpacityElement) { - fillOpacityElement.textContent = opacity; - } else { - os.xml.appendElement(os.state.v4.LayerTag.FILL_OPACITY, bfs, opacity); - } - } else { - // write tile layer opacity/alpha as alpha - value = value != null ? Number(value) : os.style.DEFAULT_FILL_ALPHA; - os.xml.appendElement(os.state.v4.LayerTag.FILL_OPACITY, layerEl, value); - } - break; case 'size': if (bfs) { value = value != null ? Math.floor(value) : os.style.DEFAULT_FEATURE_SIZE; From 4905bf2228fb5d13c5e041c31464cc7fb6b784c0 Mon Sep 17 00:00:00 2001 From: Kevin Schmidt Date: Tue, 20 Aug 2019 10:23:25 -0600 Subject: [PATCH 28/28] fix(style): use correct default image fill color --- src/os/style/style.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/os/style/style.js b/src/os/style/style.js index 80978ce25..f43e8f0bd 100644 --- a/src/os/style/style.js +++ b/src/os/style/style.js @@ -375,7 +375,7 @@ os.style.DEFAULT_VECTOR_CONFIG = { 'type': 'circle', 'radius': os.style.DEFAULT_FEATURE_SIZE, 'fill': { - 'color': os.style.DEFAULT_FILL_COLOR + 'color': os.style.DEFAULT_LAYER_COLOR } }, // this will only be applied to line and polygon types