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; |
+ } |
+} |