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