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 |
index d95a9a8eb007e58cfe40c5f947e94758ef6d3897..8672769c7f998ff7484c8a6cb0dc25a63bab6063 100644 |
--- a/third_party/WebKit/Source/devtools/front_end/ui/ShadowEditor.js |
+++ b/third_party/WebKit/Source/devtools/front_end/ui/ShadowEditor.js |
@@ -4,16 +4,259 @@ |
/** |
* @constructor |
+ * @param {!WebInspector.ShadowEditor.Shadow} shadow |
+ * @extends {WebInspector.VBox} |
*/ |
-WebInspector.ShadowEditor = function() {} |
+WebInspector.ShadowEditor = function(shadow) |
+{ |
+ WebInspector.VBox.call(this, true); |
+ this._shadow = shadow; |
lushnikov
2016/08/17 17:07:21
this._model = ..
flandy
2016/08/24 18:10:07
Done.
|
+ this._type = shadow.type(); |
+ this.registerRequiredCSS("ui/shadowEditor.css"); |
lushnikov
2016/08/17 17:07:21
this should go as the first line after super-call
flandy
2016/08/24 18:10:07
Done.
|
+ |
+ var field, label, slider; |
+ if (this._type === "box-shadow") { |
+ field = this.contentElement.createChild("div", "shadow-editor-field"); |
+ label = field.createChild("label"); |
+ label.textContent = WebInspector.UIString("Type"); |
+ this._outsetButton = field.createChild("div", "shadow-editor-button left"); |
+ this._outsetButton.textContent = WebInspector.UIString("Outset"); |
+ this._outsetButton.addEventListener("click", this._onInsetOutsetClicked.bind(this), true); |
+ this._insetButton = field.createChild("div", "shadow-editor-button right"); |
+ this._insetButton.textContent = WebInspector.UIString("Inset"); |
+ this._insetButton.addEventListener("click", this._onInsetOutsetClicked.bind(this), true); |
+ } |
+ |
+ field = this.contentElement.createChild("div", "shadow-editor-field"); |
lushnikov
2016/08/17 17:07:21
these look strikingly similar. Maybe it's possible
flandy
2016/08/24 18:10:07
Done.
|
+ label = field.createChild("label"); |
+ label.textContent = WebInspector.UIString("X offset"); |
+ label.for = "shadow-editor-x"; |
+ this._xInput = field.createChild("input"); |
+ this._xInput.type = "text"; |
+ this._xInput.id = "shadow-editor-x"; |
+ this._xInput.addEventListener("input", this._onTextInput.bind(this), true); |
+ slider = field.createChild("div", "shadow-editor-slider"); |
+ this._xSliderTrack = slider.createChild("div", "shadow-editor-slider-track"); |
+ this._xSliderThumb = this._xSliderTrack.createChild("div", "shadow-editor-slider-thumb"); |
+ WebInspector.installDragHandle(slider, this._dragStart.bind(this), this._dragX.bind(this), this._dragX.bind(this), "default"); |
lushnikov
2016/08/17 17:07:21
can you please attach a screenshot - it's hard to
flandy
2016/08/24 18:10:07
Done.
|
+ |
+ field = this.contentElement.createChild("div", "shadow-editor-field"); |
+ label = field.createChild("label"); |
+ label.textContent = WebInspector.UIString("Y offset"); |
+ label.for = "shadow-editor-y"; |
+ this._yInput = field.createChild("input"); |
+ this._yInput.type = "text"; |
+ this._yInput.id = "shadow-editor-y"; |
+ this._yInput.addEventListener("input", this._onTextInput.bind(this), true); |
+ slider = field.createChild("div", "shadow-editor-slider"); |
+ this._ySliderTrack = slider.createChild("div", "shadow-editor-slider-track"); |
+ this._ySliderThumb = this._ySliderTrack.createChild("div", "shadow-editor-slider-thumb"); |
+ WebInspector.installDragHandle(slider, this._dragStart.bind(this), this._dragY.bind(this), this._dragY.bind(this), "default"); |
lushnikov
2016/08/17 17:07:21
Why not listen to default slider changed events?
flandy
2016/08/24 18:10:07
Done.
|
+ |
+ field = this.contentElement.createChild("div", "shadow-editor-field"); |
+ label = field.createChild("label"); |
+ label.textContent = WebInspector.UIString("Blur"); |
+ label.for = "shadow-editor-blur"; |
+ this._blurInput = field.createChild("input"); |
+ this._blurInput.type = "text"; |
+ this._blurInput.id = "shadow-editor-blur"; |
+ this._blurInput.addEventListener("input", this._onTextInput.bind(this), true); |
+ slider = field.createChild("div", "shadow-editor-slider"); |
+ this._blurSliderTrack = slider.createChild("div", "shadow-editor-slider-track"); |
+ this._blurSliderThumb = this._blurSliderTrack.createChild("div", "shadow-editor-slider-thumb"); |
+ WebInspector.installDragHandle(slider, this._dragStart.bind(this), this._dragBlur.bind(this), this._dragBlur.bind(this), "default"); |
+ |
+ if (this._type === "box-shadow") { |
+ field = this.contentElement.createChild("div", "shadow-editor-field"); |
+ label = field.createChild("label"); |
+ label.textContent = WebInspector.UIString("Spread"); |
+ label.for = "shadow-editor-spread"; |
+ this._spreadInput = field.createChild("input"); |
+ this._spreadInput.type = "text"; |
+ this._spreadInput.id = "shadow-editor-spread"; |
+ this._spreadInput.addEventListener("input", this._onTextInput.bind(this), true); |
+ slider = field.createChild("div", "shadow-editor-slider"); |
+ this._spreadSliderTrack = slider.createChild("div", "shadow-editor-slider-track"); |
+ this._spreadSliderThumb = this._spreadSliderTrack.createChild("div", "shadow-editor-slider-thumb"); |
+ WebInspector.installDragHandle(slider, this._dragStart.bind(this), this._dragSpread.bind(this), this._dragSpread.bind(this), "default"); |
+ } |
+} |
+ |
+WebInspector.ShadowEditor.Events = { |
+ ShadowChanged: "ShadowChanged" |
+} |
+ |
+/** @type {number} */ |
+WebInspector.ShadowEditor.maxSliderValue = 25; |
+ |
+WebInspector.ShadowEditor.prototype = { |
+ /** |
+ * @override |
+ */ |
+ wasShown: function() |
+ { |
+ this._sliderTrackWidth = this._blurSliderTrack.offsetWidth; |
dgozman
2016/08/17 17:42:09
Should we use measureElement instead?
flandy
2016/08/24 18:10:06
Removed.
|
+ this._halfSliderThumbWidth = this._blurSliderThumb.offsetWidth / 2; |
+ this._updateUI(); |
+ }, |
+ |
+ _updateUI: function() |
+ { |
+ this._updateTextInputs(); |
+ this._updateSliders(); |
+ if (this._type === "box-shadow") { |
+ this._insetButton.classList.toggle("enabled", this._shadow.inset()); |
+ this._outsetButton.classList.toggle("enabled", !this._shadow.inset()); |
+ } |
+ }, |
+ |
+ _updateTextInputs: function() |
+ { |
+ this._xInput.value = this._shadow.xOffset().toString(); |
+ this._yInput.value = this._shadow.yOffset().toString(); |
+ this._blurInput.value = this._shadow.blur().toString(); |
+ if (this._type === "box-shadow") |
dgozman
2016/08/17 17:42:09
We should either make "box-shadow" a named constan
flandy
2016/08/24 18:10:07
Let's hide fields that are not needed.
|
+ this._spreadInput.value = this._shadow.spread().toString(); |
+ }, |
+ |
+ _updateSliders: function() |
+ { |
+ updateSlider.call(this, this._xSliderThumb, this._shadow.xOffset().amount, true); |
+ updateSlider.call(this, this._ySliderThumb, this._shadow.yOffset().amount, true); |
+ updateSlider.call(this, this._blurSliderThumb, this._shadow.blur().amount, false); |
+ if (this._type === "box-shadow") |
+ updateSlider.call(this, this._spreadSliderThumb, this._shadow.spread().amount, false); |
+ |
+ /** |
+ * @param {!Element} thumb |
+ * @param {number} amount |
+ * @param {boolean} negativeAllowed |
+ * @this {WebInspector.ShadowEditor} |
+ */ |
+ function updateSlider(thumb, amount, negativeAllowed) |
+ { |
+ amount = Number.constrain(amount, WebInspector.ShadowEditor.maxSliderValue * -1, WebInspector.ShadowEditor.maxSliderValue); |
+ var percent = amount / WebInspector.ShadowEditor.maxSliderValue; |
+ if (negativeAllowed) { |
+ if (amount < 0) |
+ percent = (amount + WebInspector.ShadowEditor.maxSliderValue) / WebInspector.ShadowEditor.maxSliderValue / 2; |
+ else |
+ percent = amount / WebInspector.ShadowEditor.maxSliderValue / 2 + 0.5; |
+ } |
+ thumb.style.left = (Number.constrain(percent, 0, 1) * this._sliderTrackWidth - this._halfSliderThumbWidth) + "px"; |
+ } |
+ }, |
+ |
+ /** |
+ * @param {!MouseEvent} event |
+ * @return {boolean} |
+ */ |
+ _dragStart: function(event) |
+ { |
+ this._sliderTrackLeft = this._blurSliderTrack.totalOffsetLeft(); |
+ return true; |
+ }, |
+ |
+ /** |
+ * @param {!MouseEvent} event |
+ */ |
+ _dragX: function(event) |
+ { |
+ this._shadow.setXAmount(this._amountFromSlider(event, true)); |
+ this._onSliderChange(); |
+ }, |
+ |
+ /** |
+ * @param {!MouseEvent} event |
+ */ |
+ _dragY: function(event) |
+ { |
+ this._shadow.setYAmount(this._amountFromSlider(event, true)); |
+ this._onSliderChange(); |
+ }, |
+ |
+ /** |
+ * @param {!MouseEvent} event |
+ */ |
+ _dragBlur: function(event) |
+ { |
+ this._shadow.setBlurAmount(this._amountFromSlider(event, false)); |
+ this._onSliderChange(); |
+ }, |
+ |
+ /** |
+ * @param {!MouseEvent} event |
+ */ |
+ _dragSpread: function(event) |
dgozman
2016/08/17 17:42:09
I'm curious why default slider handling doesn't wo
flandy
2016/08/24 18:10:07
Changed to use a default range input with custom s
|
+ { |
+ this._shadow.setSpreadAmount(this._amountFromSlider(event, false)); |
+ this._onSliderChange(); |
+ }, |
+ |
+ /** |
+ * @param {!MouseEvent} event |
+ * @param {boolean} negativeAllowed |
+ * @return {number} |
+ */ |
+ _amountFromSlider: function(event, negativeAllowed) |
+ { |
+ var offsetX = event.x - this._sliderTrackLeft; |
+ var percent = Number.constrain(offsetX / this._sliderTrackWidth, 0, 1); |
+ if (!negativeAllowed) |
+ return Math.round(percent * WebInspector.ShadowEditor.maxSliderValue); |
+ |
+ var amount; |
+ if (percent < 0.5) { |
+ percent = percent * 2; |
+ amount = percent * WebInspector.ShadowEditor.maxSliderValue - WebInspector.ShadowEditor.maxSliderValue; |
+ } else { |
+ percent = (percent - 0.5) * 2; |
+ amount = percent * WebInspector.ShadowEditor.maxSliderValue |
+ } |
+ return Math.round(amount); |
+ }, |
+ |
+ _onSliderChange: function() |
+ { |
+ this._updateSliders(); |
+ this._updateTextInputs(); |
+ this.dispatchEventToListeners(WebInspector.ShadowEditor.Events.ShadowChanged, this._shadow); |
+ }, |
+ |
+ _onInsetOutsetClicked: function() |
+ { |
+ this._insetButton.classList.toggle("enabled"); |
+ this._outsetButton.classList.toggle("enabled"); |
+ this._shadow.setInset(this._insetButton.classList.contains("enabled")); |
+ this.dispatchEventToListeners(WebInspector.ShadowEditor.Events.ShadowChanged, this._shadow); |
+ }, |
+ |
+ /** |
+ * @param {!Event} event |
+ */ |
+ _onTextInput: function(event) |
+ { |
+ if (WebInspector.ShadowEditor.Length.parse(event.currentTarget.value)) { |
+ this._shadow.setXOffset(this._xInput.value); |
+ this._shadow.setYOffset(this._yInput.value); |
+ this._shadow.setBlur(this._blurInput.value); |
+ if (this._type === "box-shadow") |
+ this._shadow.setSpread(this._spreadInput.value); |
+ this._updateSliders(); |
+ this.dispatchEventToListeners(WebInspector.ShadowEditor.Events.ShadowChanged, this._shadow); |
+ } |
+ }, |
+ |
+ __proto__: WebInspector.VBox.prototype |
+} |
/** |
* @constructor |
*/ |
WebInspector.ShadowEditor.Shadow = function(type) |
{ |
- this.type = type; |
- this.order = []; |
+ this._type = type; |
+ this._order = []; |
} |
/** |
@@ -28,7 +271,7 @@ WebInspector.ShadowEditor.Shadow.Parts = { |
/** |
* @param {string} text |
* @param {string} type |
- * @return {?Array<!WebInspector.ShadowEditor.Shadow>} |
+ * @return {!Array<!WebInspector.ShadowEditor.Shadow>} |
*/ |
WebInspector.ShadowEditor.Shadow.parse = function(text, type) |
{ |
@@ -48,24 +291,43 @@ WebInspector.ShadowEditor.Shadow.parse = function(text, type) |
var shadows = []; |
for (var i = 0; i < shadowTexts.length; i++) { |
var shadow = new WebInspector.ShadowEditor.Shadow(type); |
+ var order = []; |
var regexes = [/inset/g, WebInspector.Color.Regex, WebInspector.ShadowEditor.Length.Regex]; |
var results = WebInspector.TextUtils.splitStringByRegexes(shadowTexts[i], regexes); |
+ var numLengths = 0; |
for (var j = 0; j < results.length; j++) { |
var result = results[j]; |
if (result.regexIndex === 0) { |
- shadow.setInset(result.value); |
+ shadow.setInset(true); |
+ order.push(WebInspector.ShadowEditor.Shadow.Parts.Inset); |
} else if (result.regexIndex === 1) { |
- var color = WebInspector.Color.parse(result.value); |
- if (!color) |
- return null; |
- shadow.setColor(color); |
+ shadow.setColor(result.value) |
+ order.push(WebInspector.ShadowEditor.Shadow.Parts.Color); |
} else if (result.regexIndex === 2) { |
- var length = WebInspector.ShadowEditor.Length.parse(result.value); |
- if (!length) |
- return null; |
- shadow.addLength(length); |
+ switch (numLengths) { |
+ case 0: |
+ shadow.setXOffset(result.value); |
+ order.push(WebInspector.ShadowEditor.Shadow.Parts.Length); |
+ break; |
+ case 1: |
+ shadow.setYOffset(result.value); |
+ break; |
+ case 2: |
+ shadow.setBlur(result.value); |
+ break; |
+ case 3: |
+ shadow.setSpread(result.value); |
+ } |
+ numLengths++; |
} |
} |
+ // If inset is not specified, set inset to appear first in the css text by default. |
+ if (!order.find(part => part === WebInspector.ShadowEditor.Shadow.Parts.Inset)) |
+ order.unshift(WebInspector.ShadowEditor.Shadow.Parts.Inset); |
+ // If color is not specified, set color to appear last in the css text by default. |
+ if (!order.find(part => part === WebInspector.ShadowEditor.Shadow.Parts.Color)) |
+ order.push(WebInspector.ShadowEditor.Shadow.Parts.Color); |
+ shadow.setOrder(order); |
shadows.push(shadow); |
} |
return shadows; |
@@ -73,56 +335,183 @@ WebInspector.ShadowEditor.Shadow.parse = function(text, type) |
WebInspector.ShadowEditor.Shadow.prototype = { |
/** |
- * @param {string} inset |
+ * @param {!Array<string>} order |
+ */ |
+ setOrder: function(order) |
+ { |
+ this._order = order; |
+ }, |
+ |
+ /** |
+ * @param {boolean} inset |
*/ |
setInset: function(inset) |
{ |
- if (!this.inset) |
- this.order.push(WebInspector.ShadowEditor.Shadow.Parts.Inset); |
- this.inset = inset; |
+ this._inset = inset; |
+ }, |
+ |
+ /** |
+ * @param {string} text |
+ */ |
+ setColor: function(text) |
+ { |
+ var color = WebInspector.Color.parse(text); |
+ if (color) |
+ this._color = color; |
+ }, |
+ |
+ /** |
+ * @param {string} text |
+ */ |
+ setXOffset: function(text) |
+ { |
+ var length = WebInspector.ShadowEditor.Length.parse(text); |
+ if (length) |
+ this._xOffset = length; |
+ }, |
+ |
+ /** |
+ * @param {string} text |
+ */ |
+ setYOffset: function(text) |
+ { |
+ var length = WebInspector.ShadowEditor.Length.parse(text); |
+ if (length) |
+ this._yOffset = length; |
}, |
/** |
- * @param {!WebInspector.Color} color |
+ * @param {string} text |
*/ |
- setColor: function(color) |
+ setBlur: function(text) |
{ |
- if (!this.color) |
- this.order.push(WebInspector.ShadowEditor.Shadow.Parts.Color); |
- this.color = color; |
+ var length = WebInspector.ShadowEditor.Length.parse(text); |
+ if (length) |
+ this._blur = length; |
}, |
/** |
- * @param {!WebInspector.ShadowEditor.Length} length |
+ * @param {string} text |
*/ |
- addLength: function(length) |
+ setSpread: function(text) |
{ |
- if (!this.xOffset) { |
- this.order.push(WebInspector.ShadowEditor.Shadow.Parts.Length); |
- this.xOffset = length; |
- } else if (!this.yOffset) { |
- this.yOffset = length; |
- } else if (!this.blur) { |
- this.blur = length; |
- } else if (!this.spread) { |
- this.spread = length; |
+ var length = WebInspector.ShadowEditor.Length.parse(text); |
+ if (length) { |
+ if (!this._blur) |
+ this._blur = new WebInspector.ShadowEditor.Length(0, ""); |
+ this._spread = length; |
} |
}, |
/** |
+ * @param {number} amount |
+ */ |
+ setXAmount: function(amount) |
+ { |
+ if (this._xOffset && this._xOffset.unit) |
+ this._xOffset.amount = amount; |
+ else |
+ this._xOffset = new WebInspector.ShadowEditor.Length(amount, "px"); |
+ }, |
+ |
+ /** |
+ * @param {number} amount |
+ */ |
+ setYAmount: function(amount) |
+ { |
+ if (this._yOffset && this._yOffset.unit) |
+ this._yOffset.amount = amount; |
+ else |
+ this._yOffset = new WebInspector.ShadowEditor.Length(amount, "px"); |
+ }, |
+ |
+ |
+ /** |
+ * @param {number} amount |
+ */ |
+ setBlurAmount: function(amount) |
+ { |
+ if (this._blur && this._blur.unit) |
+ this._blur.amount = amount; |
+ else |
+ this._blur = new WebInspector.ShadowEditor.Length(amount, "px"); |
+ }, |
+ |
+ /** |
+ * @param {number} amount |
+ */ |
+ setSpreadAmount: function(amount) |
+ { |
+ if (!this._blur) |
+ this._blur = new WebInspector.ShadowEditor.Length(0, ""); |
+ if (this._spread && this._spread.unit) |
+ this._spread.amount = amount; |
+ else |
+ this._spread = new WebInspector.ShadowEditor.Length(amount, "px"); |
+ }, |
+ |
+ /** |
+ * @return {string} |
+ */ |
+ type: function() |
+ { |
+ return this._type; |
+ }, |
+ |
+ /** |
+ * @return {boolean} |
+ */ |
+ inset: function() |
+ { |
+ return !!this._inset; |
+ }, |
+ |
+ /** |
+ * @return {!WebInspector.ShadowEditor.Length} |
+ */ |
+ xOffset: function() |
+ { |
+ return this._xOffset ? this._xOffset : new WebInspector.ShadowEditor.Length(0, ""); |
+ }, |
+ |
+ /** |
+ * @return {!WebInspector.ShadowEditor.Length} |
+ */ |
+ yOffset: function() |
+ { |
+ return this._yOffset ? this._yOffset : new WebInspector.ShadowEditor.Length(0, ""); |
+ }, |
+ |
+ /** |
+ * @return {!WebInspector.ShadowEditor.Length} |
+ */ |
+ blur: function() |
+ { |
+ return this._blur ? this._blur : new WebInspector.ShadowEditor.Length(0, ""); |
+ }, |
+ |
+ /** |
+ * @return {!WebInspector.ShadowEditor.Length} |
+ */ |
+ spread: function() |
+ { |
+ return this._spread ? this._spread : new WebInspector.ShadowEditor.Length(0, ""); |
+ }, |
+ |
+ /** |
* @return {!Array<!WebInspector.ShadowEditor.Length>} |
*/ |
- lengths: function() |
+ _lengths: function() |
{ |
var lengthValues = []; |
- if (this.xOffset) |
- lengthValues.push(this.xOffset); |
- if (this.yOffset) |
- lengthValues.push(this.yOffset); |
- if (this.blur) |
- lengthValues.push(this.blur); |
- if (this.spread) |
- lengthValues.push(this.spread); |
+ if (this._xOffset) |
+ lengthValues.push(this._xOffset); |
+ if (this._yOffset) |
+ lengthValues.push(this._yOffset); |
+ if (this._blur) |
+ lengthValues.push(this._blur); |
+ if (this._spread) |
+ lengthValues.push(this._spread); |
return lengthValues; |
}, |
@@ -132,19 +521,21 @@ WebInspector.ShadowEditor.Shadow.prototype = { |
textParts: function() |
{ |
var parts = []; |
- for (var i = 0; i < this.order.length; i++) { |
- var currentPart = this.order[i]; |
- var textValue; |
- if (currentPart === WebInspector.ShadowEditor.Shadow.Parts.Inset) |
- textValue = this.inset; |
+ for (var i = 0; i < this._order.length; i++) { |
+ var currentPart = this._order[i]; |
+ var textValue = null; |
+ if (currentPart === WebInspector.ShadowEditor.Shadow.Parts.Inset && this._inset) |
+ textValue = "inset"; |
else if (currentPart === WebInspector.ShadowEditor.Shadow.Parts.Length) |
- textValue = this.lengths().join(" "); |
- else if (currentPart === WebInspector.ShadowEditor.Shadow.Parts.Color) |
- textValue = this.color.asString(this.color.format()); |
- parts.push({ |
- type: currentPart, |
- text: textValue |
- }); |
+ textValue = this._lengths().join(" "); |
+ else if (currentPart === WebInspector.ShadowEditor.Shadow.Parts.Color && this._color) |
+ textValue = this._color.asString(this._color.format()); |
+ if (textValue !== null) { |
+ parts.push({ |
+ type: currentPart, |
+ text: textValue |
+ }); |
+ } |
} |
return parts; |
} |