From a2b1935acd94dcc4ede11e797e12a1fc9d639547 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Mon, 13 Dec 2021 14:13:01 +0100 Subject: [PATCH] Add __getLayersFromStyle to stack property --- src/style_manager/index.js | 3 +- src/style_manager/model/PropertyStack.js | 70 +++++++++++++++++++- test/specs/style_manager/model/Properties.js | 16 +++-- 3 files changed, 82 insertions(+), 7 deletions(-) diff --git a/src/style_manager/index.js b/src/style_manager/index.js index 9450b7338..955a2307c 100644 --- a/src/style_manager/index.js +++ b/src/style_manager/index.js @@ -568,8 +568,9 @@ export default () => { sector.getProperties().map(prop => { this.__upProp(prop, style, parentStyles, opts); const props = prop.getProperties?.(); + const isStack = prop.getType() === 'stack'; - if (props && prop.getType() !== 'stack') { + if (props && !isStack) { const newStyle = prop.__getFromStyle(style); const newParentStyles = parentStyles.map(p => ({ ...p, diff --git a/src/style_manager/model/PropertyStack.js b/src/style_manager/model/PropertyStack.js index 99f7e7b82..14081851d 100644 --- a/src/style_manager/model/PropertyStack.js +++ b/src/style_manager/model/PropertyStack.js @@ -1,4 +1,4 @@ -import { keys, isUndefined } from 'underscore'; +import { keys, isUndefined, isArray, isString } from 'underscore'; import Property from './PropertyComposite'; import PropertyBase from './Property'; import Layers from './Layers'; @@ -7,6 +7,13 @@ import { camelCase } from 'utils/mixins'; const VALUES_REG = /,(?![^\(]*\))/; const PARTS_REG = /\s(?![^(]*\))/; +const splitStyleName = (style, name, sep) => { + return (style[name] || '') + .split(sep) + .map(value => value.trim()) + .filter(Boolean); +}; + export default Property.extend({ defaults: { ...Property.prototype.defaults, @@ -128,6 +135,49 @@ export default Property.extend({ return fromStyle ? fromStyle(style) : style; }, + __getLayersFromStyle(style = {}) { + const name = this.getName(); + const props = this.getProperties(); + const nameProps = props.map(prop => prop.getName()); + const allNameProps = [name, ...nameProps]; + const hasProps = allNameProps.some(prop => !isUndefined(style[prop])); + + if (!hasProps) { + return []; + } else { + const fromStyle = this.get('fromStyle'); + let result = fromStyle ? fromStyle(style, { property: this }) : []; + + if (!fromStyle) { + const sep = this.getLayerSeparator(); + const sepParts = this.getPartsSeparator(); + // Get layers from the main property + const layers = splitStyleName(style, name, sep) + .map(value => value.split(sepParts)) + .map(parts => { + const result = {}; + props.forEach((prop, i) => { + const value = parts[i]; + result[prop.getId()] = !isUndefined(value) ? value : prop.getDefaultValue(); + }); + return result; + }); + // Get layers from the inner properties + props.forEach(prop => { + const id = prop.getId(); + splitStyleName(style, prop.getName(), sep) + .map(value => ({ [id]: value || prop.getDefaultValue() })) + .forEach((inLayer, i) => { + layers[i] = layers[i] ? { ...layers[i], ...inLayer } : inLayer; + }); + }); + result = layers; + } + + return isArray(result) ? result : [result]; + } + }, + hasValue(opts) { return PropertyBase.prototype.hasValue.call(this, opts); }, @@ -237,6 +287,24 @@ export default Property.extend({ .join(this.get('layerSeparator')); }, + /** + * Get layer sperator + * @return {RegExp} + */ + getLayerSeparator() { + const sep = this.get('layerSeparator'); + return isString(sep) ? new RegExp(`${sep}(?![^\\(]*\\))`) : sep; + }, + + /** + * Get layer parts sperator + * @return {RegExp} + */ + getPartsSeparator() { + const sep = this.get('partsSeparator') || ' '; + return isString(sep) ? new RegExp(`${sep}(?![^\\(]*\\))`) : sep; + }, + getLayers() { return this.get('layers'); }, diff --git a/test/specs/style_manager/model/Properties.js b/test/specs/style_manager/model/Properties.js index cfcfbb35f..72db09ce5 100644 --- a/test/specs/style_manager/model/Properties.js +++ b/test/specs/style_manager/model/Properties.js @@ -93,7 +93,9 @@ describe('StyleManager properties logic', () => { const propATest = `${propTest}-a`; const propBTest = `${propTest}-b`; const propCTest = `${propTest}-c`; + const propsTest = [propATest, propBTest, propCTest]; const propStyleValue = 'valueA-1 valueB-1 valueC-1, valueA-2 valueB-2 valueC-2'; + const propStyleExtValue = 'valueC-1-ext, valueC-2-ext'; let compTypeProp; let compTypePropInn; @@ -101,6 +103,7 @@ describe('StyleManager properties logic', () => { rule1 = cssc.addRules(` .cls { ${propTest}: ${propStyleValue}; + ${propCTest}: ${propStyleExtValue}; } `)[0]; obj.addSector(sectorTest, { @@ -108,7 +111,7 @@ describe('StyleManager properties logic', () => { { type: 'stack', property: propTest, - properties: [{ property: propATest }, { property: propBTest }, { property: propCTest }], + properties: propsTest.map(property => ({ property })), }, ], }); @@ -132,21 +135,24 @@ describe('StyleManager properties logic', () => { expect(compTypeProp.getSelectedLayer()).toBe(null); }); - test('Layers has the right values', () => { + test.only('Layers has the right values', () => { expect(compTypeProp.getLayer(0).getValues()).toEqual({ [propATest]: 'valueA-1', [propBTest]: 'valueB-1', - [propCTest]: 'valueC-1', + [propCTest]: 'valueC-1-ext', }); expect(compTypeProp.getLayer(1).getValues()).toEqual({ [propATest]: 'valueA-2', [propBTest]: 'valueB-2', - [propCTest]: 'valueC-2', + [propCTest]: 'valueC-2-ext', }); }); test('Updating inner property, it reflects on the rule', () => { - expect(rule1.getStyle()).toEqual({ [propTest]: propStyleValue }); + expect(rule1.getStyle()).toEqual({ + [propTest]: propStyleValue, + [propCTest]: propStyleExtValue, + }); compTypeProp.selectLayerAt(0); compTypeProp.getProperty(propBTest).upValue('valueB-1-mod'); compTypeProp.selectLayerAt(1);