Chromium Code Reviews| Index: third_party/WebKit/Source/devtools/front_end/ui/CSSShadowEditor.js |
| diff --git a/third_party/WebKit/Source/devtools/front_end/ui/CSSShadowEditor.js b/third_party/WebKit/Source/devtools/front_end/ui/CSSShadowEditor.js |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..b7039f889f3f4423585c7b7398ed99d0b3dc9489 |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/devtools/front_end/ui/CSSShadowEditor.js |
| @@ -0,0 +1,203 @@ |
| +// 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 |
| + * @param {!WebInspector.CSSShadowModel} model |
| + * @extends {WebInspector.VBox} |
| + */ |
| +WebInspector.CSSShadowEditor = function(model) |
| +{ |
| + WebInspector.VBox.call(this, true); |
| + this.registerRequiredCSS("ui/cssShadowEditor.css"); |
| + this.contentElement.tabIndex = 0; |
| + |
| + this._model = model; |
| + |
| + this._typeField = this.contentElement.createChild("div", "shadow-editor-field"); |
| + var label = this._typeField.createChild("label", "shadow-editor-label"); |
| + label.textContent = WebInspector.UIString("Type"); |
|
dgozman
2016/08/24 19:18:30
Inline |label| here.
flandy
2016/08/24 22:08:41
Done.
|
| + this._outsetButton = this._typeField.createChild("button", "shadow-editor-button left"); |
|
dgozman
2016/08/24 19:18:30
"left" is too generic for css class. Let's do shad
flandy
2016/08/24 22:08:41
Done.
|
| + this._outsetButton.createTextChild(WebInspector.UIString("Outset")); |
| + this._outsetButton.addEventListener("click", this._onButtonClick.bind(this), true); |
| + this._insetButton = this._typeField.createChild("button", "shadow-editor-button right"); |
| + this._insetButton.createTextChild(WebInspector.UIString("Inset")); |
|
dgozman
2016/08/24 19:18:30
Just textContent = ... ?
flandy
2016/08/24 22:08:41
Done.
|
| + this._insetButton.addEventListener("click", this._onButtonClick.bind(this), true); |
| + |
| + var inputs; |
| + inputs = this._createSliderField("X offset", true); |
|
dgozman
2016/08/24 19:18:30
Always UIString the literal, do not pass it raw.
flandy
2016/08/24 22:08:41
I called UIString in the function, but I suppose I
|
| + this._xInput = inputs.textInput; |
| + this._xSlider = inputs.rangeInput; |
| + inputs = this._createSliderField("Y offset", true); |
| + this._yInput = inputs.textInput; |
| + this._ySlider = inputs.rangeInput; |
| + inputs = this._createSliderField("Blur", false); |
| + this._blurInput = inputs.textInput; |
| + this._blurSlider = inputs.rangeInput; |
| + inputs = this._createSliderField("Spread", false); |
| + this._spreadInput = inputs.textInput; |
| + this._spreadSlider = inputs.rangeInput; |
| + this._spreadField = inputs.field; |
| + |
| + this._updateUI(); |
| +} |
| + |
| +/** @enum {symbol} */ |
| +WebInspector.CSSShadowEditor.Events = { |
| + ShadowChanged: Symbol("ShadowChanged") |
| +} |
| + |
| +/** @type {number} */ |
| +WebInspector.CSSShadowEditor.maxRange = 40; |
| +/** @type {string} */ |
| +WebInspector.CSSShadowEditor.defaultUnit = "px"; |
| + |
| +WebInspector.CSSShadowEditor.prototype = { |
| + /** |
| + * @param {string} propertyName |
| + * @param {boolean} negativeAllowed |
| + * @return {{textInput: !Element, rangeInput: !Element, field: !Element}} |
| + */ |
| + _createSliderField: function(propertyName, negativeAllowed) |
| + { |
| + var field = this.contentElement.createChild("div", "shadow-editor-field"); |
| + var label = field.createChild("label", "shadow-editor-label"); |
| + label.textContent = WebInspector.UIString(propertyName); |
| + label.htmlFor = propertyName; |
|
dgozman
2016/08/24 19:18:30
Use setAttribute.
flandy
2016/08/24 22:08:41
Done.
|
| + var textInput = field.createChild("input", "shadow-editor-text-input"); |
| + textInput.type = "text"; |
| + textInput.id = propertyName; |
| + textInput.addEventListener("input", this._onTextInput.bind(this), true); |
|
dgozman
2016/08/24 19:18:30
Why do we capture all events?
flandy
2016/08/24 22:08:41
We want any valid changes to be reflected immediat
dgozman
2016/08/24 23:26:58
I was talking about last parameter being |true|. S
flandy
2016/08/25 00:17:47
Oh I see, done!
|
| + textInput.addEventListener("blur", this._onTextBlur.bind(this), true); |
| + var halfRange = WebInspector.CSSShadowEditor.maxRange / 2; |
| + var slider = negativeAllowed ? createSliderLabel(halfRange * -1, halfRange) : createSliderLabel(0, WebInspector.CSSShadowEditor.maxRange); |
|
dgozman
2016/08/24 19:18:30
-halfRange
flandy
2016/08/24 22:08:41
Done.
|
| + slider.addEventListener("input", this._onSliderInput.bind(this), true); |
| + field.appendChild(slider); |
| + return {field: field, textInput: textInput, rangeInput: slider}; |
| + }, |
| + |
| + hideBoxShadowProperties: function() |
|
dgozman
2016/08/24 19:18:30
Isn't this class reused? We should.
flandy
2016/08/24 22:08:41
Is CSSShadowEditor re-used for text-shadows? Yes.
dgozman
2016/08/24 23:26:58
What I meant is that creating an editor every time
flandy
2016/08/25 00:17:47
Thanks for clarifying. Done.
|
| + { |
| + this._typeField.hidden = true; |
|
dgozman
2016/08/24 19:18:30
Figure that out from this._model.
flandy
2016/08/24 22:08:41
Done.
|
| + this._spreadField.hidden = true; |
| + }, |
| + |
| + _updateUI: function() |
| + { |
| + this._updateButtons(); |
| + this._updateSliders(); |
| + this._xInput.value = this._model.offsetX().asCSSText(); |
| + this._yInput.value = this._model.offsetY().asCSSText(); |
| + this._blurInput.value = this._model.blurRadius().asCSSText(); |
| + this._spreadInput.value = this._model.spreadRadius().asCSSText(); |
| + }, |
| + |
| + _updateButtons: function() |
| + { |
| + this._insetButton.classList.toggle("enabled", this._model.inset()); |
| + this._outsetButton.classList.toggle("enabled", !this._model.inset()); |
| + }, |
| + |
| + _updateSliders: function() |
| + { |
| + this._xSlider.value = this._model.offsetX().amount; |
| + this._ySlider.value = this._model.offsetY().amount; |
| + this._blurSlider.value = this._model.blurRadius().amount; |
| + this._spreadSlider.value = this._model.spreadRadius().amount; |
| + }, |
| + |
| + /** |
| + * @param {!Event} event |
| + */ |
| + _onButtonClick: function(event) |
| + { |
| + var insetClicked = (event.currentTarget === this._insetButton); |
| + if (insetClicked && this._model.inset() || !insetClicked && !this._model.inset()) |
| + return; |
| + this._model.setInset(insetClicked); |
| + this._updateButtons(); |
| + this.dispatchEventToListeners(WebInspector.CSSShadowEditor.Events.ShadowChanged, this._model); |
| + }, |
| + |
| + /** |
| + * @param {!Event} event |
| + */ |
| + _onTextInput: function(event) |
| + { |
| + this._changedElement = event.currentTarget; |
| + this._changedElement.classList.toggle("invalid", false); |
| + var length = WebInspector.CSSLength.parse(event.currentTarget.value); |
| + if (!length || event.currentTarget === this._blurInput && length.amount < 0) |
| + return; |
| + if (event.currentTarget === this._xInput) |
| + this._model.setOffset(length, this._model.offsetY()); |
|
dgozman
2016/08/24 19:18:30
Why don't we have separate setOffsetX and setOffse
flandy
2016/08/24 22:08:41
Done.
|
| + else if (event.currentTarget === this._yInput) |
| + this._model.setOffset(this._model.offsetX(), length); |
| + else if (event.currentTarget === this._blurInput) |
| + this._model.setBlurRadius(length); |
| + else if (event.currentTarget === this._spreadInput) |
| + this._model.setSpreadRadius(length); |
| + this._updateSliders(); |
|
dgozman
2016/08/24 19:18:30
Let's update them separately as we do for inputs.
flandy
2016/08/24 22:08:41
Done.
|
| + this.dispatchEventToListeners(WebInspector.CSSShadowEditor.Events.ShadowChanged, this._model); |
| + }, |
| + |
| + _onTextBlur: function() |
| + { |
| + if (!this._changedElement) |
| + return; |
| + var length = this._changedElement.value === "" ? WebInspector.CSSLength.zero() : WebInspector.CSSLength.parse(this._changedElement.value); |
|
dgozman
2016/08/24 19:18:30
x === "" should be !x
flandy
2016/08/24 22:08:41
Done.
|
| + if (!length) |
| + length = WebInspector.CSSLength.parse(this._changedElement.value + WebInspector.CSSShadowEditor.defaultUnit); |
| + if (!length) { |
| + this._changedElement.classList.add("invalid"); |
| + this._changedElement = null; |
| + return; |
| + } |
| + if (this._changedElement === this._xInput) { |
| + this._model.setOffset(length, this._model.offsetY()); |
| + this._xInput.value = this._model.offsetX().asCSSText(); |
| + } else if (this._changedElement === this._yInput) { |
| + this._model.setOffset(this._model.offsetX(), length); |
| + this._yInput.value = this._model.offsetY().asCSSText(); |
| + } else if (this._changedElement === this._blurInput) { |
| + if (length.amount < 0) |
| + length = WebInspector.CSSLength.zero(); |
| + this._model.setBlurRadius(length); |
| + this._blurInput.value = this._model.blurRadius().asCSSText(); |
| + } else if (this._changedElement === this._spreadInput) { |
| + this._model.setSpreadRadius(length); |
| + this._spreadInput.value = this._model.spreadRadius().asCSSText(); |
| + } |
| + this._changedElement = null; |
| + this._updateSliders(); |
| + this.dispatchEventToListeners(WebInspector.CSSShadowEditor.Events.ShadowChanged, this._model); |
| + }, |
| + |
| + /** |
| + * @param {!Event} event |
| + */ |
| + _onSliderInput: function(event) |
| + { |
| + if (event.currentTarget === this._xSlider) { |
| + this._model.setOffset(new WebInspector.CSSLength(this._xSlider.value, this._model.offsetX().unit || WebInspector.CSSShadowEditor.defaultUnit), this._model.offsetY()); |
| + this._xInput.value = this._model.offsetX().asCSSText(); |
| + this._xInput.classList.toggle("invalid", false); |
| + } else if (event.currentTarget === this._ySlider) { |
| + this._model.setOffset(this._model.offsetX(), new WebInspector.CSSLength(this._ySlider.value, this._model.offsetY().unit || WebInspector.CSSShadowEditor.defaultUnit)); |
| + this._yInput.value = this._model.offsetY().asCSSText(); |
| + this._yInput.classList.toggle("invalid", false); |
| + } else if (event.currentTarget === this._blurSlider) { |
| + this._model.setBlurRadius(new WebInspector.CSSLength(this._blurSlider.value, this._model.blurRadius().unit || WebInspector.CSSShadowEditor.defaultUnit)); |
| + this._blurInput.value = this._model.blurRadius().asCSSText(); |
| + this._blurInput.classList.toggle("invalid", false); |
| + } else if (event.currentTarget === this._spreadSlider) { |
| + this._model.setSpreadRadius(new WebInspector.CSSLength(this._spreadSlider.value, this._model.spreadRadius().unit || WebInspector.CSSShadowEditor.defaultUnit)); |
| + this._spreadInput.value = this._model.spreadRadius().asCSSText(); |
| + this._spreadInput.classList.toggle("invalid", false); |
| + } |
| + this.dispatchEventToListeners(WebInspector.CSSShadowEditor.Events.ShadowChanged, this._model); |
| + }, |
| + |
| + __proto__: WebInspector.VBox.prototype |
| +} |