Chromium Code Reviews| Index: third_party/WebKit/Source/devtools/front_end/ui/ShadowEditor.js |
| diff --git a/third_party/WebKit/Source/devtools/front_end/ui/ShadowEditor.js b/third_party/WebKit/Source/devtools/front_end/ui/ShadowEditor.js |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..fd045c21c2529dcb85c04b76eb85136ff9ddaf9c |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/devtools/front_end/ui/ShadowEditor.js |
| @@ -0,0 +1,326 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +/** |
| + * @constructor |
| + */ |
| +WebInspector.ShadowEditor = function() {} |
| + |
| +/** |
| + * @constructor |
| + * @param {boolean=} inset |
|
lushnikov
2016/08/19 16:24:35
let's make non-optional
flandy
2016/08/19 21:50:39
Done.
|
| + * @param {!WebInspector.CSSLength=} x |
| + * @param {!WebInspector.CSSLength=} y |
| + * @param {!WebInspector.CSSLength=} blurRadius |
| + * @param {!WebInspector.CSSLength=} spreadRadius |
| + * @param {!WebInspector.Color=} color |
| + */ |
| +WebInspector.CSSShadowModel = function(inset, x, y, blurRadius, spreadRadius, color) |
|
lushnikov
2016/08/19 16:24:35
This model is a good patch by itself.
Let's extra
flandy
2016/08/19 21:50:40
Done.
|
| +{ |
| + this._inset = !!inset; |
| + this._x = x || new WebInspector.CSSLength(0, WebInspector.CSSLengthUnit.None); |
|
lushnikov
2016/08/19 16:24:35
let's introduce a convenience method: WebInspector
flandy
2016/08/19 21:50:39
Done.
|
| + this._y = y || new WebInspector.CSSLength(0, WebInspector.CSSLengthUnit.None); |
|
lushnikov
2016/08/19 16:24:35
let's name these and all related local variables a
flandy
2016/08/19 21:50:39
Done.
|
| + this._blurRadius = blurRadius || new WebInspector.CSSLength(0, WebInspector.CSSLengthUnit.None); |
| + this._spreadRadius = spreadRadius || new WebInspector.CSSLength(0, WebInspector.CSSLengthUnit.None); |
| + this._color = color; |
| + this._format = ""; |
|
lushnikov
2016/08/19 16:24:35
there should be some default format - otherwise, t
flandy
2016/08/19 21:50:39
Done.
|
| +} |
| + |
| +/** |
| + * @enum {string} |
| + */ |
| +WebInspector.CSSShadowModel.FormatParts = { |
| + Inset: "I", |
| + X: "X", |
| + Y: "Y", |
| + BlurRadius: "B", |
| + SpreadRadius: "S", |
| + Color: "C" |
| +} |
| + |
| +/** |
| + * @param {string} text |
| + * @return {?Array<!WebInspector.CSSShadowModel>} |
|
lushnikov
2016/08/19 16:24:35
let's return !Array<..>, which would be empty in c
flandy
2016/08/19 21:50:39
Done.
|
| + */ |
| +WebInspector.CSSShadowModel.parseTextShadow = function(text) |
| +{ |
| + return WebInspector.CSSShadowModel._parseShadow(text, false); |
| +} |
| + |
| +/** |
| + * @param {string} text |
| + * @return {?Array<!WebInspector.CSSShadowModel>} |
| + */ |
| +WebInspector.CSSShadowModel.parseBoxShadow = function(text) |
| +{ |
| + return WebInspector.CSSShadowModel._parseShadow(text, true); |
| +} |
| + |
| +WebInspector.CSSShadowModel.prototype = { |
| + /** |
| + * @param {boolean} inset |
| + */ |
| + setInset: function(inset) |
| + { |
| + this._inset = inset; |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.CSSLength} x |
| + * @param {!WebInspector.CSSLength} y |
| + */ |
| + setOffset: function(x, y) |
| + { |
| + this._x = x; |
| + this._y = y; |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.CSSLength} blurRadius |
| + */ |
| + setBlurRadius: function(blurRadius) |
| + { |
| + this._blurRadius = blurRadius; |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.CSSLength} spreadRadius |
| + */ |
| + setSpreadRadius: function(spreadRadius) |
| + { |
| + this._spreadRadius = spreadRadius; |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.Color} color |
| + */ |
| + setColor: function(color) |
| + { |
| + this._color = color; |
| + }, |
| + |
| + /** |
| + * @param {string} format |
| + */ |
| + setFormat: function(format) |
| + { |
| + this._format = format; |
| + }, |
| + |
| + /** |
| + * @return {!WebInspector.CSSLength} |
| + */ |
| + xOffset: function() |
| + { |
| + return this._x; |
| + }, |
| + |
| + /** |
| + * @return {!WebInspector.CSSLength} |
| + */ |
| + yOffset: function() |
| + { |
| + return this._y; |
| + }, |
| + |
| + /** |
| + * @return {string} |
| + */ |
| + asCSSText: function() |
| + { |
| + var parts = []; |
| + for (var i = 0; i < this._format.length; i++) { |
| + var part = this._format.charAt(i); |
| + if (part === WebInspector.CSSShadowModel.FormatParts.Inset && this._inset) |
| + parts.push("inset"); |
| + else if (part === WebInspector.CSSShadowModel.FormatParts.X) |
| + parts.push(this._x.asCSSText()); |
| + else if (part === WebInspector.CSSShadowModel.FormatParts.Y) |
| + parts.push(this._y.asCSSText()); |
| + else if (part === WebInspector.CSSShadowModel.FormatParts.BlurRadius) |
| + parts.push(this._blurRadius.asCSSText()); |
| + else if (part === WebInspector.CSSShadowModel.FormatParts.SpreadRadius) |
| + parts.push(this._spreadRadius.asCSSText()); |
| + else if (part === WebInspector.CSSShadowModel.FormatParts.Color && this._color) |
| + parts.push(this._color.asString(this._color.format())); |
| + } |
| + return parts.join(" "); |
| + } |
| +} |
| + |
| +/** |
| + * @param {string} text |
| + * @param {boolean} isBoxShadow |
| + * @return {?Array<!WebInspector.CSSShadowModel>} |
| + */ |
| +WebInspector.CSSShadowModel._parseShadow = function(text, isBoxShadow) |
| +{ |
| + var shadowTexts = []; |
| + // Split by commas that aren't inside of color values to get the individual shadow values. |
| + var splits = WebInspector.TextUtils.splitStringByRegexes(text, [WebInspector.Color.Regex, /,/g]); |
| + var currentIndex = 0; |
| + for (var i = 0; i < splits.length; i++) { |
| + if (splits[i].regexIndex === 1) { |
| + var comma = splits[i]; |
| + shadowTexts.push(text.substring(currentIndex, comma.position)); |
| + currentIndex = comma.position + 1; |
| + } |
| + } |
| + shadowTexts.push(text.substring(currentIndex, text.length)); |
| + |
| + var shadows = []; |
| + for (var i = 0; i < shadowTexts.length; i++) { |
| + var shadow = new WebInspector.CSSShadowModel(); |
| + var format = ""; |
| + var nextPartAllowed = true; |
| + var regexes = [/inset/gi, WebInspector.Color.Regex, WebInspector.CSSLength.Regex]; |
| + var results = WebInspector.TextUtils.splitStringByRegexes(shadowTexts[i], regexes); |
| + for (var j = 0; j < results.length; j++) { |
| + var result = results[j]; |
| + if (result.regexIndex === -1) { |
| + // Don't allow anything other than inset, color, length values, and whitespace. |
| + if (/\S/.test(result.value)) |
| + return null; |
| + // All parts must be separated by whitespace. |
| + nextPartAllowed = true; |
| + } else { |
| + if (!nextPartAllowed) |
| + return null; |
| + nextPartAllowed = false; |
| + |
| + if (result.regexIndex === 0) { |
| + shadow.setInset(true); |
| + format += WebInspector.CSSShadowModel.FormatParts.Inset; |
| + } else if (result.regexIndex === 1) { |
| + var color = WebInspector.Color.parse(result.value); |
| + if (!color) |
| + return null; |
| + shadow.setColor(color); |
| + format += WebInspector.CSSShadowModel.FormatParts.Color; |
| + } else if (result.regexIndex === 2) { |
| + var length = WebInspector.CSSLength.parse(result.value); |
| + if (!length) |
| + return null; |
| + var previousPart = format.length > 0 ? format.charAt(format.length - 1) : ""; |
| + if (previousPart === WebInspector.CSSShadowModel.FormatParts.X) { |
| + shadow.setOffset(shadow.xOffset(), length); |
| + format += WebInspector.CSSShadowModel.FormatParts.Y; |
| + } else if (previousPart === WebInspector.CSSShadowModel.FormatParts.Y) { |
| + shadow.setBlurRadius(length); |
| + format += WebInspector.CSSShadowModel.FormatParts.BlurRadius; |
| + } else if (previousPart === WebInspector.CSSShadowModel.FormatParts.BlurRadius) { |
| + shadow.setSpreadRadius(length); |
| + format += WebInspector.CSSShadowModel.FormatParts.SpreadRadius; |
| + } else { |
| + shadow.setOffset(length, shadow.yOffset()); |
| + format += WebInspector.CSSShadowModel.FormatParts.X; |
| + } |
| + } |
| + } |
| + } |
| + if (invalidCount(WebInspector.CSSShadowModel.FormatParts.X, 1, 1) |
| + || invalidCount(WebInspector.CSSShadowModel.FormatParts.Y, 1, 1) |
| + || invalidCount(WebInspector.CSSShadowModel.FormatParts.Color, 0, 1) |
| + || invalidCount(WebInspector.CSSShadowModel.FormatParts.BlurRadius, 0, 1) |
| + || invalidCount(WebInspector.CSSShadowModel.FormatParts.Inset, 0, isBoxShadow ? 1 : 0) |
| + || invalidCount(WebInspector.CSSShadowModel.FormatParts.SpreadRadius, 0, isBoxShadow ? 1 : 0)) |
| + return null; |
| + shadow.setFormat(format); |
| + shadows.push(shadow); |
| + } |
| + return shadows; |
| + |
| + /** |
| + * @param {string} character |
| + * @param {number} min |
| + * @param {number} max |
| + * @return {boolean} |
| + */ |
| + function invalidCount(character, min, max) |
| + { |
| + var count = 0; |
| + for (var i = 0; i < format.length; i++) { |
| + if (format.charAt(i) === character) |
| + count++; |
| + } |
| + return count < min || count > max; |
| + } |
| +} |
| + |
| +/** |
| + * @constructor |
| + * @param {number} amount |
| + * @param {string} unit |
|
lushnikov
2016/08/19 16:24:35
WebInspector.CSSLengthUnit
flandy
2016/08/19 21:50:39
Done.
|
| + */ |
| +WebInspector.CSSLength = function(amount, unit) |
| +{ |
| + this.amount = amount; |
| + this.unit = unit; |
| +} |
| + |
| +/** @type {!RegExp} */ |
| +WebInspector.CSSLength.Regex = /([+-]?(?:[0-9]*[.])?[0-9]+(?:[eE][+-]?[0-9]+)?)([a-zA-Z]{2,4})|[+-]?(?:0*[.])?0+(?:[eE][+-]?[0-9]+)?/g; |
|
lushnikov
2016/08/19 16:24:35
can we build this complex regex out of composing p
flandy
2016/08/19 21:50:39
Done.
|
| + |
| +/** |
| + * @enum {string} |
| + */ |
| +WebInspector.CSSLengthUnit = { |
| + Ch: "ch", |
| + Cm: "cm", |
| + Em: "em", |
| + Ex: "ex", |
| + In: "in", |
| + Mm: "mm", |
| + Pc: "pc", |
| + Pt: "pt", |
| + Px: "px", |
| + Rem: "rem", |
| + Vh: "vh", |
| + Vmax: "vmax", |
| + Vmin: "vmin", |
| + Vw: "vw", |
| + None: "" |
| +} |
| + |
| +/** |
| + * @param {string} text |
| + * @return {?WebInspector.CSSLength} |
| + */ |
| +WebInspector.CSSLength.parse = function(text) |
| +{ |
| + var lengthRegex = new RegExp("^(" + WebInspector.CSSLength.Regex.source + ")$"); |
| + var match = text.match(lengthRegex) || []; |
| + if (match.length > 3 && match[3]) { |
| + if (validUnit(match[3])) |
| + return new WebInspector.CSSLength(parseFloat(match[2]), match[3]); |
| + } else if (match.length > 1) { |
| + return new WebInspector.CSSLength(0, WebInspector.CSSLengthUnit.None); |
| + } |
| + return null; |
| + |
| + /** |
| + * @param {string} unit |
| + * @return {boolean} |
| + */ |
| + function validUnit(unit) |
|
lushnikov
2016/08/19 16:24:35
this can go away if the CSSLengthUnit regex would
flandy
2016/08/19 21:50:40
Done.
|
| + { |
| + unit = unit.toLowerCase(); |
| + var keys = Object.keys(WebInspector.CSSLengthUnit); |
| + for (var i = 0; i < keys.length; i++) { |
| + if (WebInspector.CSSLengthUnit[keys[i]] === unit) |
| + return true; |
| + } |
| + return false; |
| + } |
| +} |
| + |
| +WebInspector.CSSLength.prototype = { |
| + /** |
| + * @return {string} |
| + */ |
| + asCSSText: function() |
| + { |
| + return this.amount + this.unit; |
| + } |
| +} |