From b3240f1a4ed83e5fdb6a5ac401daee44da50254c Mon Sep 17 00:00:00 2001 From: Oussama MESSAOUDI Date: Mon, 29 Mar 2021 15:43:36 +0000 Subject: [PATCH] [FIX] website: properly retrieve gray parameters from gray values - Retrieve the correct value for hue and extra-saturation parameters. - Dynamically set the max, min value of the extra-saturation slider. Linked PR: https://github.com/odoo/odoo/pull/66428 Part of https://github.com/odoo/odoo/pull/68488 closes odoo/odoo#68849 X-original-commit: 9f5b9dd3a9659283708a32885b49618364798cac Signed-off-by: Quentin Smetz (qsm) Co-authored-by: qsm-odoo --- .../static/src/js/editor/snippets.options.js | 103 ++++++++++++++---- addons/website/views/snippets/snippets.xml | 6 +- 2 files changed, 85 insertions(+), 24 deletions(-) diff --git a/addons/website/static/src/js/editor/snippets.options.js b/addons/website/static/src/js/editor/snippets.options.js index f5637bf2c86..87bb3b387ef 100644 --- a/addons/website/static/src/js/editor/snippets.options.js +++ b/addons/website/static/src/js/editor/snippets.options.js @@ -810,6 +810,8 @@ options.registry.BackgroundVideo = options.Class.extend({ }); options.registry.OptionsTab = options.Class.extend({ + GRAY_PARAMS: {EXTRA_SATURATION: "gray-extra-saturation", HUE: "gray-hue"}, + /** * @override */ @@ -827,14 +829,63 @@ options.registry.OptionsTab = options.Class.extend({ * @override */ async updateUI() { - await this._super(...arguments); - // The bg-XXX classes have been updated (and could be updated by another // option like changing color palette) -> remove the inline style that // was added for gray previews. this.$el.find(".o_we_gray_preview").each((_, e) => { e.style.removeProperty("background-color"); }); + + // If the gray palette has been generated by Odoo standard option, + // the hue of all gray is the same and the saturation has been + // increased/decreased by the same amount for all grays in + // comparaison with BS grays. However the system supports any + // gray palette. + + const hues = []; + const saturationDiffs = []; + let oneHasNoSaturation = false; + for (let id = 100; id <= 900; id += 100) { + const gray = weUtils.getCSSVariableValue(`${id}`); + const grayRGB = ColorpickerWidget.convertCSSColorToRgba(gray); + const grayHSL = ColorpickerWidget.convertRgbToHsl(grayRGB.red, grayRGB.green, grayRGB.blue); + + const baseGray = weUtils.getCSSVariableValue(`base-${id}`); + const baseGrayRGB = ColorpickerWidget.convertCSSColorToRgba(baseGray); + const baseGrayHSL = ColorpickerWidget.convertRgbToHsl(baseGrayRGB.red, baseGrayRGB.green, baseGrayRGB.blue); + + if (grayHSL.saturation > 0.01) { + if (grayHSL.lightness > 0.01 && grayHSL.lightness < 99.99) { + hues.push(grayHSL.hue); + } + if (grayHSL.saturation < 99.99) { + saturationDiffs.push(grayHSL.saturation - baseGrayHSL.saturation); + } + } else { + oneHasNoSaturation = true; + } + } + this.grayHueIsDefined = !!hues.length; + + // Average of angles: we need to take the average of found hues + // because even if grays are supposed to be set to the exact + // same hue by the Odoo editor, there might be rounding errors + // during the conversion from RGB to HSL as the HSL system + // allows to represent more colors that the RGB hexadecimal + // notation (also: hue 360 = hue 0 and should not be averaged to 180). + // This also better support random gray palettes. + this.grayParams[this.GRAY_PARAMS.HUE] = (!hues.length) ? 0 : Math.round((Math.atan2( + hues.map(hue => Math.sin(hue * Math.PI / 180)).reduce((memo, value) => memo + value, 0) / hues.length, + hues.map(hue => Math.cos(hue * Math.PI / 180)).reduce((memo, value) => memo + value, 0) / hues.length + ) * 180 / Math.PI) + 360) % 360; + + // Average of found saturation diffs, or all grays have no + // saturation, or all grays are fully saturated. + this.grayParams[this.GRAY_PARAMS.EXTRA_SATURATION] = saturationDiffs.length + ? saturationDiffs.reduce((memo, value) => memo + value, 0) / saturationDiffs.length + : (oneHasNoSaturation ? -100 : 100); + + await this._super(...arguments); }, //-------------------------------------------------------------------------- @@ -1012,11 +1063,35 @@ options.registry.OptionsTab = options.Class.extend({ const gray = weUtils.getCSSVariableValue(`base-${id}`); const grayRGB = ColorpickerWidget.convertCSSColorToRgba(gray); const hsl = ColorpickerWidget.convertRgbToHsl(grayRGB.red, grayRGB.green, grayRGB.blue); - const adjustedGrayRGB = ColorpickerWidget.convertHslToRgb(this.grayParams['gray-hue'], - Math.min(Math.max(hsl.saturation + this.grayParams['gray-extra-saturation'], 0), 100), + const adjustedGrayRGB = ColorpickerWidget.convertHslToRgb(this.grayParams[this.GRAY_PARAMS.HUE], + Math.min(Math.max(hsl.saturation + this.grayParams[this.GRAY_PARAMS.EXTRA_SATURATION], 0), 100), hsl.lightness); return ColorpickerWidget.convertRgbaToCSSColor(adjustedGrayRGB.red, adjustedGrayRGB.green, adjustedGrayRGB.blue); }, + /** + * @override + */ + async _renderCustomXML(uiFragment) { + await this._super(...arguments); + const extraSaturationRangeEl = uiFragment.querySelector(`we-range[data-param=${this.GRAY_PARAMS.EXTRA_SATURATION}]`); + if (extraSaturationRangeEl) { + const baseGrays = _.range(100, 1000, 100).map(id => { + const gray = weUtils.getCSSVariableValue(`base-${id}`); + const grayRGB = ColorpickerWidget.convertCSSColorToRgba(gray); + const hsl = ColorpickerWidget.convertRgbToHsl(grayRGB.red, grayRGB.green, grayRGB.blue); + return {id: id, hsl: hsl}; + }); + const first = baseGrays[0]; + const maxValue = baseGrays.reduce((gray, value) => { + return gray.hsl.saturation > value.hsl.saturation ? gray : value; + }, first); + const minValue = baseGrays.reduce((gray, value) => { + return gray.hsl.saturation < value.hsl.saturation ? gray : value; + }, first); + extraSaturationRangeEl.dataset.max = 100 - minValue.hsl.saturation; + extraSaturationRangeEl.dataset.min = -maxValue.hsl.saturation; + } + }, /** * @override */ @@ -1048,22 +1123,7 @@ options.registry.OptionsTab = options.Class.extend({ return weUtils.getCSSVariableValue('body-image-type'); } if (methodName === 'customizeGray') { - // If the gray palette has been generated by Odoo standard option, - // the hue of all gray is the same and the saturation has been - // increased/decreased by the same amount for all grays in - // comparaison with BS grays. However the system supports any - // gray palette so we base our hue and extra saturation displayed - // values on one gray, let's say the middle one: gray-500. - const gray = weUtils.getCSSVariableValue('500'); - const grayRGB = ColorpickerWidget.convertCSSColorToRgba(gray); - const hsl = ColorpickerWidget.convertRgbToHsl(grayRGB.red, grayRGB.green, grayRGB.blue); - - const baseGray = weUtils.getCSSVariableValue('base-500'); - const baseGrayRGB = ColorpickerWidget.convertCSSColorToRgba(baseGray); - const baseHSL = ColorpickerWidget.convertRgbToHsl(baseGrayRGB.red, baseGrayRGB.green, baseGrayRGB.blue); - - this.grayParams['gray-hue'] = hsl.hue; - this.grayParams['gray-extra-saturation'] = hsl.saturation - baseHSL.saturation; + // See updateUI override return this.grayParams[params.param]; } return this._super(...arguments); @@ -1075,6 +1135,9 @@ options.registry.OptionsTab = options.Class.extend({ if (widgetName === 'body_bg_image_opt') { return false; } + if (params.param === this.GRAY_PARAMS.HUE) { + return this.grayHueIsDefined; + } return this._super(...arguments); }, /** diff --git a/addons/website/views/snippets/snippets.xml b/addons/website/views/snippets/snippets.xml index 8767ac1c1dc..23b01cbc466 100644 --- a/addons/website/views/snippets/snippets.xml +++ b/addons/website/views/snippets/snippets.xml @@ -1218,10 +1218,8 @@ t-attf-class="o_we_user_value_widget o_we_gray_preview bg-#{grayCode}"/> - - + +