Suggested in https://bugs.webkit.org/show_bug.cgi?id=148310
<rdar://problem/23232369>
Created attachment 265567 [details] Patch
Created attachment 265568 [details] After patch is applied
By the way, I worked on this with less than 3 hours of sleep during HackSC, so there may be obvious errors...
Comment on attachment 265567 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=265567&action=review Cool! I'll let someone else review, but this looks great. > Source/WebInspectorUI/ChangeLog:112 > + Reworked into VisualStyleBackgroundEditor.js. Typo: VisualStyleBackgroundPicker.js > Source/WebInspectorUI/UserInterface/Views/GradientEditor.js:2 > + * Copyright (C) 2015 Devin Rousso <dcrousso+webkit@gmail.com>. All rights reserved. Since a lot of this code came from an existing file with a copyright, it should have both you and the original ("Copyright (C) 2014 Apple Inc. All rights reserved.") > Source/WebInspectorUI/UserInterface/Views/VisualStyleBackgroundPicker.js:194 > + _valueInputValueChanged(event) { Style: Brace on new line > Source/WebInspectorUI/UserInterface/Views/VisualStyleBackgroundPicker.js:207 > + _handleKeywordChanged(event) { Style: Brace on new line
Comment on attachment 265567 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=265567&action=review >> Source/WebInspectorUI/UserInterface/Views/GradientEditor.js:2 >> + * Copyright (C) 2015 Devin Rousso <dcrousso+webkit@gmail.com>. All rights reserved. > > Since a lot of this code came from an existing file with a copyright, it should have both you and the original ("Copyright (C) 2014 Apple Inc. All rights reserved.") Ah OK gotcha. I wasn't really sure how to go about doing that, but what you wrote makes sense. Thanks! >> Source/WebInspectorUI/UserInterface/Views/VisualStyleBackgroundPicker.js:194 >> + _valueInputValueChanged(event) { > > Style: Brace on new line Oops.
Comment on attachment 265567 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=265567&action=review > Source/WebInspectorUI/UserInterface/Controllers/CodeMirrorGradientEditingController.js:63 > + this._gradientEditor.addEventListener(WebInspector.GradientEditor.Event.ColorPickerToggled, popover.update, popover); It is usually better to have a wrapper listener to make sure the function isn't confused by the first argument being an event object.
Created attachment 265942 [details] Patch
Comment on attachment 265942 [details] Patch >diff --git a/Source/WebInspectorUI/ChangeLog b/Source/WebInspectorUI/ChangeLog >index bb02dcf..591e236 100644 >--- a/Source/WebInspectorUI/ChangeLog >+++ b/Source/WebInspectorUI/ChangeLog >@@ -1,3 +1,116 @@ >+2015-11-20 Devin Rousso <dcrousso+webkit@gmail.com> >+ >+ Web Inspector: Add support for Gradients in the Visual sidebar background editor >+ https://bugs.webkit.org/show_bug.cgi?id=150494 >+ >+ Reviewed by Timothy Hatcher. >+ >+ Allows the editors in the Visual sidebar Background Style section to >+ work with gradients and data URIs. >+ >+ * Localizations/en.lproj/localizedStrings.js: >+ * UserInterface/Controllers/CodeMirrorGradientEditingController.css: Deleted. >+ Some styling was reused in VisualStyleBackgroundPicker.css. >+ >+ * UserInterface/Controllers/CodeMirrorGradientEditingController.js: >+ (WebInspector.CodeMirrorGradientEditingController): >+ (WebInspector.CodeMirrorGradientEditingController.prototype.popoverWillPresent): >+ (WebInspector.CodeMirrorGradientEditingController.prototype.popoverDidPresent): >+ (WebInspector.CodeMirrorGradientEditingController.prototype._gradientEditorGradientChanged): >+ (WebInspector.CodeMirrorGradientEditingController.prototype.handleEvent): Deleted. >+ (WebInspector.CodeMirrorGradientEditingController.prototype.gradientSliderStopsDidChange): Deleted. >+ (WebInspector.CodeMirrorGradientEditingController.prototype.gradientSliderStopWasSelected): Deleted. >+ (WebInspector.CodeMirrorGradientEditingController.prototype.dragToAdjustControllerWasAdjustedByAmount): Deleted. >+ (WebInspector.CodeMirrorGradientEditingController.prototype._handleInputEvent): Deleted. >+ (WebInspector.CodeMirrorGradientEditingController.prototype._angleInputValueDidChange): Deleted. >+ (WebInspector.CodeMirrorGradientEditingController.prototype._handleChangeEvent): Deleted. >+ (WebInspector.CodeMirrorGradientEditingController.prototype._colorPickerColorChanged): Deleted. >+ (WebInspector.CodeMirrorGradientEditingController.prototype._updateCSSClassForGradientType): Deleted. >+ Reworked gradient editor popup into WebInspector.GradientEditor. >+ >+ * UserInterface/Main.html: >+ * UserInterface/Models/Gradient.js: >+ (WebInspector.Gradient.fromString): >+ (WebInspector.Gradient.stopsWithComponents): >+ (WebInspector.LinearGradient.linearGradientWithComponents): >+ Removed console.error statements as they didn't do anything but clog the console. >+ >+ * UserInterface/Views/GradientEditor.css: Added. >+ (.gradient-editor): >+ (.gradient-editor.radial-gradient): >+ (.gradient-editor.editing-color): >+ (.gradient-editor.radial-gradient.editing-color): >+ (.gradient-editor > .gradient-type-select): >+ (.gradient-editor > .gradient-slider): >+ (.gradient-editor > .color-picker): >+ (.gradient-editor > .color-picker > .slider): >+ (.gradient-editor > .color-picker > .brightness): >+ (.gradient-editor > .color-picker > .opacity): >+ (.gradient-editor > .gradient-angle): >+ (.gradient-editor.radial-gradient > .gradient-angle): >+ (.gradient-editor > .gradient-angle > input): >+ >+ * UserInterface/Views/GradientEditor.js: Added. >+ (WebInspector.GradientEditor): >+ (WebInspector.GradientEditor.prototype.get element): >+ (WebInspector.GradientEditor.prototype.set gradient): >+ (WebInspector.GradientEditor.prototype.get gradient): >+ (WebInspector.GradientEditor.prototype.gradientSliderStopsDidChange): >+ (WebInspector.GradientEditor.prototype.gradientSliderStopWasSelected): >+ (WebInspector.GradientEditor.prototype.dragToAdjustControllerWasAdjustedByAmount): >+ (WebInspector.GradientEditor.prototype._updateCSSClassForGradientType): >+ (WebInspector.GradientEditor.prototype._gradientTypeChanged): >+ (WebInspector.GradientEditor.prototype._colorPickerColorChanged): >+ (WebInspector.GradientEditor.prototype._angleChanged): >+ (WebInspector.GradientEditor.prototype._angleInputValueDidChange): >+ New standalone editor for CSS Gradients. >+ >+ * UserInterface/Views/VisualStyleBackgroundPicker.css: Added. >+ (.visual-style-property-container.background-picker > .visual-style-property-value-container): >+ (.visual-style-property-container.background-picker > .visual-style-property-value-container > .color-gradient-swatch): >+ (.visual-style-property-container.background-picker > .visual-style-property-value-container > .color-gradient-swatch:hover): >+ (.visual-style-property-container.background-picker > .visual-style-property-value-container > .color-gradient-swatch:active): >+ (.visual-style-property-container.background-picker > .visual-style-property-value-container > .color-gradient-swatch > span): >+ (.visual-style-property-container.background-picker > .visual-style-property-value-container.gradient-value > .color-gradient-swatch): >+ (.visual-style-property-container.background-picker > .visual-style-property-value-container.gradient-value > .color-gradient-swatch + .value-input): >+ (.visual-style-property-container.background-picker > .visual-style-property-value-container > .value-input): >+ (.visual-style-property-container.background-picker > .visual-style-property-value-container > .value-input[disabled]): >+ (.visual-style-property-container.background-picker > .visual-style-property-value-container > .value-type-picker-select): >+ >+ * UserInterface/Views/VisualStyleBackgroundPicker.js: Added. >+ (WebInspector.VisualStyleBackgroundPicker): >+ (WebInspector.VisualStyleBackgroundPicker.prototype.get value): >+ (WebInspector.VisualStyleBackgroundPicker.prototype.set value): >+ (WebInspector.VisualStyleBackgroundPicker.prototype.get synthesizedValue): >+ (WebInspector.VisualStyleBackgroundPicker.prototype.parseValue): >+ (WebInspector.VisualStyleBackgroundPicker.prototype._updateValueInput): >+ (WebInspector.VisualStyleBackgroundPicker.prototype._updateGradientSwatch): >+ (WebInspector.VisualStyleBackgroundPicker.prototype._gradientSwatchClicked): >+ (WebInspector.VisualStyleBackgroundPicker.prototype._gradientEditorGradientChanged): >+ (WebInspector.VisualStyleBackgroundPicker.prototype._valueInputValueChanged): >+ (WebInspector.VisualStyleBackgroundPicker.prototype._keywordSelectMouseDown): >+ (WebInspector.VisualStyleBackgroundPicker.prototype._handleKeywordChanged): >+ (WebInspector.VisualStyleBackgroundPicker.prototype._createValueOptions): >+ (WebInspector.VisualStyleBackgroundPicker.prototype._addAdvancedValues): >+ (WebInspector.VisualStyleBackgroundPicker.prototype._removeAdvancedValues): >+ (WebInspector.VisualStyleBackgroundPicker.prototype._toggleTabbingOfSelectableElements): >+ Visual property editor for the CSS background-image property. Supports >+ limited keywords, as well as url() and gradients. >+ >+ * UserInterface/Views/VisualStyleCommaSeparatedKeywordEditor.js: >+ (WebInspector.VisualStyleCommaSeparatedKeywordEditor.prototype.set value): >+ Fixed regular expression parsing to not match commas inside parenthesis. >+ >+ * UserInterface/Views/VisualStyleDetailsPanel.js: >+ (WebInspector.VisualStyleDetailsPanel.prototype._populateBackgroundStyleSection): >+ >+ * UserInterface/Views/VisualStylePropertyEditorLink.css: >+ (.visual-style-property-editor-link:not(.link-all) > .visual-style-property-editor-link-border): >+ Fixed spacing of link line. >+ >+ * UserInterface/Views/VisualStyleURLInput.js: Removed. >+ Reworked into VisualStyleBackgroundPicker.js. >+ > 2015-11-19 Brian Burg <bburg@apple.com> > > Web Inspector: yank/kill shortcuts (CTRL+Y, K) don't work in Console / QuickConsole >diff --git a/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js b/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js >index 60c7fe9bb19d9ca823f11df69ecf21ff3b5b8c7e..2b542f7c7786794dadc4266f1db45d8ae0ec7374 100644 >GIT binary patch >delta 145 >zcmezLgr(yJ%Z7N{$^2#<lWlE;7}F;!JdvLK*Gve?i+f@@Ip36PbG+>f_sPoZg(h>a >z=b9YZDgb0#O`h2*u-U!!#$tPKhE#@1hH{2{h9ZU(1_g#NhD3%OhEkxY5<@JIZwtgq >d4519g44Djh4Cz1~ijK(vo6WZiYcj@j0stifD;fX* > >delta 29 >lcmeBp!Sd+|%Z7N{&3|oQxKFNa<Jg?sc46`Mty+x1oB-)@4p#sG > >diff --git a/Source/WebInspectorUI/UserInterface/Controllers/CodeMirrorGradientEditingController.css b/Source/WebInspectorUI/UserInterface/Controllers/CodeMirrorGradientEditingController.css >deleted file mode 100644 >index 30e1af9..0000000 >--- a/Source/WebInspectorUI/UserInterface/Controllers/CodeMirrorGradientEditingController.css >+++ /dev/null >@@ -1,117 +0,0 @@ >-/* >- * Copyright (C) 2014 Apple Inc. All rights reserved. >- * >- * Redistribution and use in source and binary forms, with or without >- * modification, are permitted provided that the following conditions >- * are met: >- * 1. Redistributions of source code must retain the above copyright >- * notice, this list of conditions and the following disclaimer. >- * 2. Redistributions in binary form must reproduce the above copyright >- * notice, this list of conditions and the following disclaimer in the >- * documentation and/or other materials provided with the distribution. >- * >- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >- * THE POSSIBILITY OF SUCH DAMAGE. >- */ >- >-.gradient-editing-controller { >- width: 260px; >- height: 109px; >-} >- >-.gradient-editing-controller.edits-color { >- height: 306px; >-} >- >-.gradient-editing-controller.radial-gradient { >- height: 78px; >-} >- >-.gradient-editing-controller.edits-color.radial-gradient { >- height: 275px; >-} >- >-.gradient-editing-controller select { >- position: absolute; >- left: 17px; >- top: 9px; >- width: 237px; >- >- font-size: 16px; >-} >- >-.gradient-editing-controller .gradient-slider { >- left: 16px; >- right: 26px; >- top: 42px; >-} >- >-.gradient-editing-controller .color-picker { >- position: absolute; >- >- top: 86px; >- width: 202px; >- height: 172px; >- padding: 0 10px; >-} >- >-.gradient-editing-controller > .color-picker > .slider { >- top: 2px; >- width: 186px; >-} >- >-.gradient-editing-controller > .color-picker > .brightness { >- left: 214px; >-} >- >-.gradient-editing-controller > .color-picker > .opacity { >- left: 237px; >-} >- >-.gradient-editing-controller > label { >- position: absolute; >- top: 85px; >- right: 16px; >- >- text-align: right; >- font-size: 13px; >-} >- >-.gradient-editing-controller.radial-gradient > label { >- display: none; >-} >- >-.gradient-editing-controller.edits-color > label { >- top: 283px; >-} >- >-.gradient-editing-controller > label > input { >- width: 48px; >- >- padding-right: 4px; >- margin-left: 5px; >- >- background-color: white; >- >- border-radius: 4px; >- border: 1px solid hsl(0, 0%, 60%); >- box-shadow: inset 0 0 1px 1px hsl(0, 0%, 89%); >- outline: 0; >- >- font-size: 13px; >- text-align: right; >-} >- >-.gradient-editing-controller > label.drag-to-adjust, >-.gradient-editing-controller > label.drag-to-adjust > input { >- cursor: col-resize; >-} >diff --git a/Source/WebInspectorUI/UserInterface/Controllers/CodeMirrorGradientEditingController.js b/Source/WebInspectorUI/UserInterface/Controllers/CodeMirrorGradientEditingController.js >index e1e16a5..7ff38e0 100644 >--- a/Source/WebInspectorUI/UserInterface/Controllers/CodeMirrorGradientEditingController.js >+++ b/Source/WebInspectorUI/UserInterface/Controllers/CodeMirrorGradientEditingController.js >@@ -28,34 +28,6 @@ WebInspector.CodeMirrorGradientEditingController = class CodeMirrorGradientEditi > constructor(codeMirror, marker) > { > super(codeMirror, marker); >- >- if (!WebInspector.CodeMirrorGradientEditingController.GradientTypes) { >- WebInspector.CodeMirrorGradientEditingController.GradientTypes = { >- "linear-gradient": { >- type: WebInspector.LinearGradient, >- label: WebInspector.UIString("Linear Gradient"), >- repeats: false >- }, >- >- "radial-gradient": { >- type: WebInspector.RadialGradient, >- label: WebInspector.UIString("Radial Gradient"), >- repeats: false >- }, >- >- "repeating-linear-gradient": { >- type: WebInspector.LinearGradient, >- label: WebInspector.UIString("Repeating Linear Gradient"), >- repeats: true >- }, >- >- "repeating-radial-gradient": { >- type: WebInspector.RadialGradient, >- label: WebInspector.UIString("Repeating Radial Gradient"), >- repeats: true >- } >- }; >- } > } > > // Public >@@ -86,162 +58,26 @@ WebInspector.CodeMirrorGradientEditingController = class CodeMirrorGradientEditi > > popoverWillPresent(popover) > { >- this._container = document.createElement("div"); >- this._container.className = WebInspector.CodeMirrorGradientEditingController.StyleClassName; >- >- this._gradientTypePicker = this._container.appendChild(document.createElement("select")); >- for (var type in WebInspector.CodeMirrorGradientEditingController.GradientTypes) { >- var option = this._gradientTypePicker.appendChild(document.createElement("option")); >- option.value = type; >- option.innerText = WebInspector.CodeMirrorGradientEditingController.GradientTypes[type].label; >+ function handleColorPickerToggled(event) >+ { >+ popover.update(); > } >- this._gradientTypePicker.addEventListener("change", this); >- >- this._gradientSlider = new WebInspector.GradientSlider; >- this._container.appendChild(this._gradientSlider.element); > >- this._colorPicker = new WebInspector.ColorPicker; >- this._colorPicker.colorWheel.dimension = 190; >- this._colorPicker.addEventListener(WebInspector.ColorPicker.Event.ColorChanged, this._colorPickerColorChanged, this); >- >- var angleLabel = this._container.appendChild(document.createElement("label")); >- angleLabel.textContent = WebInspector.UIString("Angle"); >- >- this._angleInput = document.createElement("input"); >- this._angleInput.type = "text"; >- this._angleInput.size = 3; >- this._angleInput.addEventListener("input", this); >- angleLabel.appendChild(this._angleInput); >- >- var dragToAdjustController = new WebInspector.DragToAdjustController(this); >- dragToAdjustController.element = angleLabel; >- dragToAdjustController.enabled = true; >- >- this._updateCSSClassForGradientType(); >- >- popover.content = this._container; >+ this._gradientEditor = new WebInspector.GradientEditor; >+ this._gradientEditor.addEventListener(WebInspector.GradientEditor.Event.GradientChanged, this._gradientEditorGradientChanged, this); >+ this._gradientEditor.addEventListener(WebInspector.GradientEditor.Event.ColorPickerToggled, handleColorPickerToggled, this); >+ popover.content = this._gradientEditor.element; > } > > popoverDidPresent(popover) > { >- this._gradientSlider.stops = this.value.stops; >- >- if (this.value instanceof WebInspector.LinearGradient) { >- this._gradientTypePicker.value = this.value.repeats ? "repeating-linear-gradient" : "linear-gradient"; >- this._angleInput.value = this.value.angle + "\u00B0"; >- } else >- this._gradientTypePicker.value = this.value.repeats ? "repeating-radial-gradient" : "radial-gradient"; >- >- this._gradientSlider.delegate = this; >- } >- >- // Protected >- >- handleEvent(event) >- { >- if (event.type === "input") >- this._handleInputEvent(event); >- else if (event.type === "change") >- this._handleChangeEvent(event); >- } >- >- gradientSliderStopsDidChange(gradientSlider) >- { >- this.text = this.value.toString(); >- } >- >- gradientSliderStopWasSelected(gradientSlider, stop) >- { >- var selectedStop = gradientSlider.selectedStop; >- >- if (selectedStop && !this._container.classList.contains(WebInspector.CodeMirrorGradientEditingController.EditsColorClassName)) { >- this._container.appendChild(this._colorPicker.element); >- this._container.classList.add(WebInspector.CodeMirrorGradientEditingController.EditsColorClassName); >- this._colorPicker.color = selectedStop.color; >- } else if (!selectedStop) { >- this._colorPicker.element.remove(); >- this._container.classList.remove(WebInspector.CodeMirrorGradientEditingController.EditsColorClassName); >- } >- >- // Ensure the angle input is not focused since, if it were, it'd make a scrollbar appear as we >- // animate the popover's frame to fit its new content. >- this._angleInput.blur(); >- >- this.popover.update(); >- } >- >- dragToAdjustControllerWasAdjustedByAmount(dragToAdjustController, amount) >- { >- var angle = parseFloat(this._angleInput.value) + amount; >- if (Math.round(angle) !== angle) >- angle = angle.toFixed(1); >- >- this._angleInput.value = angle; >- this._angleInputValueDidChange(angle); >+ this._gradientEditor.gradient = this.value; > } > > // Private > >- _handleInputEvent(event) >+ _gradientEditorGradientChanged(event) > { >- var angle = parseFloat(this._angleInput.value); >- if (isNaN(angle)) >- return; >- >- this._angleInputValueDidChange(angle); >- } >- >- _angleInputValueDidChange(angle) >- { >- this.value.angle = angle; >- this.text = this.value.toString(); >- >- var matches = this._angleInput.value.match(/\u00B0/g); >- if (!matches || matches.length !== 1) { >- var selectionStart = this._angleInput.selectionStart; >- this._angleInput.value = angle + "\u00B0"; >- this._angleInput.selectionStart = selectionStart; >- this._angleInput.selectionEnd = selectionStart; >- } >- } >- >- _handleChangeEvent(event) >- { >- var descriptor = WebInspector.CodeMirrorGradientEditingController.GradientTypes[this._gradientTypePicker.value]; >- if (!(this.value instanceof descriptor.type)) { >- if (descriptor.type === WebInspector.LinearGradient) { >- this.value = new WebInspector.LinearGradient(180, this.value.stops); >- this._angleInput.value = "180\u00B0"; >- } else >- this.value = new WebInspector.RadialGradient("", this.value.stops); >- >- this._updateCSSClassForGradientType(); >- this.popover.update(); >- } >- this.value.repeats = descriptor.repeats; >- this.text = this.value.toString(); >- } >- >- _colorPickerColorChanged(event) >- { >- this._gradientSlider.selectedStop.color = event.target.color; >- this._gradientSlider.stops = this.value.stops; >- this.text = this.value.toString(); >- } >- >- _updateCSSClassForGradientType() >- { >- if (this.value instanceof WebInspector.LinearGradient) >- this._container.classList.remove(WebInspector.CodeMirrorGradientEditingController.RadialGradientClassName); >- else >- this._container.classList.add(WebInspector.CodeMirrorGradientEditingController.RadialGradientClassName); >+ this.value = event.data.gradient; > } > }; >- >-WebInspector.CodeMirrorGradientEditingController.StyleClassName = "gradient-editing-controller"; >-WebInspector.CodeMirrorGradientEditingController.EditsColorClassName = "edits-color"; >-WebInspector.CodeMirrorGradientEditingController.RadialGradientClassName = "radial-gradient"; >- >-// Lazily populated in the WebInspector.CodeMirrorGradientEditingController constructor. >-// It needs to be lazy to use UIString after Main.js and localizedStrings.js loads. >-WebInspector.CodeMirrorGradientEditingController.GradientTypes = null; >diff --git a/Source/WebInspectorUI/UserInterface/Main.html b/Source/WebInspectorUI/UserInterface/Main.html >index 6be42c2..8b5f72c 100644 >--- a/Source/WebInspectorUI/UserInterface/Main.html >+++ b/Source/WebInspectorUI/UserInterface/Main.html >@@ -87,6 +87,7 @@ > <link rel="stylesheet" href="Views/FontResourceContentView.css"> > <link rel="stylesheet" href="Views/FormattedValue.css"> > <link rel="stylesheet" href="Views/GoToLineDialog.css"> >+ <link rel="stylesheet" href="Views/GradientEditor.css"> > <link rel="stylesheet" href="Views/GradientSlider.css"> > <link rel="stylesheet" href="Views/HierarchicalPathComponent.css"> > <link rel="stylesheet" href="Views/HoverMenu.css"> >@@ -164,6 +165,7 @@ > <link rel="stylesheet" href="Views/TypeTreeElement.css"> > <link rel="stylesheet" href="Views/TypeTreeView.css"> > <link rel="stylesheet" href="Views/Variables.css"> >+ <link rel="stylesheet" href="Views/VisualStyleBackgroundPicker.css"> > <link rel="stylesheet" href="Views/VisualStyleColorPicker.css"> > <link rel="stylesheet" href="Views/VisualStyleCommaSeparatedKeywordEditor.css"> > <link rel="stylesheet" href="Views/VisualStyleDetailsPanel.css"> >@@ -181,7 +183,6 @@ > > <link rel="stylesheet" href="Controllers/CodeMirrorCompletionController.css"> > <link rel="stylesheet" href="Controllers/CodeMirrorDragToAdjustNumberController.css"> >- <link rel="stylesheet" href="Controllers/CodeMirrorGradientEditingController.css"> > <link rel="stylesheet" href="Controllers/CodeMirrorTokenTrackingController.css"> > > <script src="External/CodeMirror/codemirror.js"></script> >@@ -470,6 +471,7 @@ > <script src="Views/GeneralTreeElementPathComponent.js"></script> > <script src="Views/GenericResourceContentView.js"></script> > <script src="Views/GoToLineDialog.js"></script> >+ <script src="Views/GradientEditor.js"></script> > <script src="Views/GradientSlider.js"></script> > <script src="Views/HierarchicalPathNavigationItem.js"></script> > <script src="Views/HoverMenu.js"></script> >@@ -566,6 +568,7 @@ > > <script src="Views/VisualStyleDetailsPanel.js"></script> > <script src="Views/VisualStylePropertyEditor.js"></script> >+ <script src="Views/VisualStyleBackgroundPicker.js"></script> > <script src="Views/VisualStyleColorPicker.js"></script> > <script src="Views/VisualStyleCommaSeparatedKeywordEditor.js"></script> > <script src="Views/VisualStyleFontFamilyListEditor.js"></script> >@@ -583,7 +586,6 @@ > <script src="Views/VisualStyleTabbedPropertiesRow.js"></script> > <script src="Views/VisualStyleTimingEditor.js"></script> > <script src="Views/VisualStyleUnitSlider.js"></script> >- <script src="Views/VisualStyleURLInput.js"></script> > > <script src="Controllers/Annotator.js"></script> > <script src="Controllers/CodeMirrorEditingController.js"></script> >diff --git a/Source/WebInspectorUI/UserInterface/Models/Gradient.js b/Source/WebInspectorUI/UserInterface/Models/Gradient.js >index 3e4ff6c..a094f3b 100644 >--- a/Source/WebInspectorUI/UserInterface/Models/Gradient.js >+++ b/Source/WebInspectorUI/UserInterface/Models/Gradient.js >@@ -39,10 +39,8 @@ WebInspector.Gradient = { > type = WebInspector.Gradient.Types.Linear; > else if (typeString.indexOf(WebInspector.Gradient.Types.Radial) !== -1) > type = WebInspector.Gradient.Types.Radial; >- else { >- console.error("Couldn't parse angle \"" + typeString + "\""); >+ else > return null; >- } > > var components = []; > var currentParams = []; >@@ -112,10 +110,8 @@ WebInspector.Gradient = { > } > }); > >- if (!stops.length) { >- console.error("Couldn't parse any stops"); >+ if (!stops.length) > return null; >- } > > for (var i = 0, count = stops.length; i < count; ++i) { > var stop = stops[i]; >@@ -190,7 +186,6 @@ WebInspector.LinearGradient = class LinearGradient > angle = 315; > break; > default: >- console.error("Couldn't parse angle \"to " + components[0].join(" ") + "\""); > return null; > } > components.shift(); >diff --git a/Source/WebInspectorUI/UserInterface/Views/GradientEditor.css b/Source/WebInspectorUI/UserInterface/Views/GradientEditor.css >new file mode 100644 >index 0000000..8446318 >--- /dev/null >+++ b/Source/WebInspectorUI/UserInterface/Views/GradientEditor.css >@@ -0,0 +1,99 @@ >+/* >+ * Copyright (C) 2015 Devin Rousso <dcrousso+webkit@gmail.com>. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+.gradient-editor { >+ position: relative; >+ margin: 5px 11px; >+ padding-bottom: 45px; >+} >+ >+.gradient-editor.radial-gradient { >+ padding-bottom: 15px; >+} >+ >+.gradient-editor.editing-color { >+ padding-bottom: 30px; >+} >+ >+.gradient-editor.radial-gradient.editing-color { >+ padding-bottom: 0; >+} >+ >+.gradient-editor > .gradient-type-select { >+ width: 237px; >+ margin-left: 1px; >+ font-size: 16px; >+} >+ >+.gradient-editor > .gradient-slider { >+ position: relative; >+ left: auto; >+ margin-top: 7px; >+} >+ >+.gradient-editor > .color-picker { >+ width: 238px; >+ height: auto; >+ margin-top: 25px; >+ padding: 0; >+} >+ >+.gradient-editor > .color-picker > .slider { >+ top: 2px; >+ width: 186px; >+} >+ >+.gradient-editor > .color-picker > .brightness { >+ left: 202px; >+} >+ >+.gradient-editor > .color-picker > .opacity { >+ left: 228px; >+} >+ >+.gradient-editor > .gradient-angle { >+ position: absolute; >+ right: 0; >+ bottom: 0; >+ text-align: right; >+ font-size: 13px; >+} >+ >+.gradient-editor.radial-gradient > .gradient-angle { >+ display: none; >+} >+ >+.gradient-editor > .gradient-angle > input { >+ width: 48px; >+ margin-left: 5px; >+ padding-right: 4px; >+ text-align: right; >+ font-size: 13px; >+ background-color: white; >+ border-radius: 4px; >+ border: 1px solid hsl(0, 0%, 60%); >+ box-shadow: inset 0 0 1px 1px hsl(0, 0%, 89%); >+ outline: none; >+} >diff --git a/Source/WebInspectorUI/UserInterface/Views/GradientEditor.js b/Source/WebInspectorUI/UserInterface/Views/GradientEditor.js >new file mode 100644 >index 0000000..441701e >--- /dev/null >+++ b/Source/WebInspectorUI/UserInterface/Views/GradientEditor.js >@@ -0,0 +1,229 @@ >+/* >+ * Copyright (C) 2014 Apple Inc. All rights reserved. >+ * Copyright (C) 2015 Devin Rousso <dcrousso+webkit@gmail.com>. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+WebInspector.GradientEditor = class GradientEditor extends WebInspector.Object >+{ >+ constructor() >+ { >+ super(); >+ >+ this._element = document.createElement("div"); >+ this._element.classList.add("gradient-editor"); >+ >+ this._gradient = null; >+ this._gradientTypes = { >+ "linear-gradient": { >+ type: WebInspector.LinearGradient, >+ label: WebInspector.UIString("Linear Gradient"), >+ repeats: false >+ }, >+ "radial-gradient": { >+ type: WebInspector.RadialGradient, >+ label: WebInspector.UIString("Radial Gradient"), >+ repeats: false >+ }, >+ "repeating-linear-gradient": { >+ type: WebInspector.LinearGradient, >+ label: WebInspector.UIString("Repeating Linear Gradient"), >+ repeats: true >+ }, >+ "repeating-radial-gradient": { >+ type: WebInspector.RadialGradient, >+ label: WebInspector.UIString("Repeating Radial Gradient"), >+ repeats: true >+ } >+ }; >+ this._editingColor = false; >+ >+ this._gradientTypePicker = this._element.appendChild(document.createElement("select")); >+ this._gradientTypePicker.classList.add("gradient-type-select"); >+ for (let type in this._gradientTypes) { >+ let option = this._gradientTypePicker.appendChild(document.createElement("option")); >+ option.value = type; >+ option.text = this._gradientTypes[type].label; >+ } >+ this._gradientTypePicker.addEventListener("change", this._gradientTypeChanged.bind(this)); >+ >+ this._gradientSlider = new WebInspector.GradientSlider(this); >+ this._element.appendChild(this._gradientSlider.element); >+ >+ this._colorPicker = new WebInspector.ColorPicker; >+ this._colorPicker.colorWheel.dimension = 190; >+ this._colorPicker.addEventListener(WebInspector.ColorPicker.Event.ColorChanged, this._colorPickerColorChanged, this); >+ >+ let angleLabel = this._element.appendChild(document.createElement("label")); >+ angleLabel.classList.add("gradient-angle"); >+ angleLabel.append(WebInspector.UIString("Angle")); >+ >+ this._angleInput = angleLabel.appendChild(document.createElement("input")); >+ this._angleInput.type = "text"; >+ this._angleInput.addEventListener("input", this._angleChanged.bind(this)); >+ >+ let dragToAdjustController = new WebInspector.DragToAdjustController(this); >+ dragToAdjustController.element = angleLabel; >+ dragToAdjustController.enabled = true; >+ } >+ >+ get element() >+ { >+ return this._element; >+ } >+ >+ set gradient(gradient) >+ { >+ if (!gradient) >+ return; >+ >+ const isLinear = gradient instanceof WebInspector.LinearGradient; >+ const isRadial = gradient instanceof WebInspector.RadialGradient; >+ console.assert(isLinear || isRadial); >+ if (!isLinear && !isRadial) >+ return; >+ >+ this._gradient = gradient; >+ this._gradientSlider.stops = this._gradient.stops; >+ if (isLinear) { >+ this._gradientTypePicker.value = this._gradient.repeats ? "repeating-linear-gradient" : "linear-gradient"; >+ this._angleInput.value = this._gradient.angle + "\u00B0"; >+ } else >+ this._gradientTypePicker.value = this._gradient.repeats ? "repeating-radial-gradient" : "radial-gradient"; >+ >+ this._updateCSSClassForGradientType(); >+ } >+ >+ get gradient() >+ { >+ return this._gradient; >+ } >+ >+ // Protected >+ >+ gradientSliderStopsDidChange(gradientSlider) >+ { >+ this._gradient.stops = gradientSlider.stops; >+ >+ this.dispatchEventToListeners(WebInspector.GradientEditor.Event.GradientChanged, {gradient: this._gradient}); >+ } >+ >+ gradientSliderStopWasSelected(gradientSlider, stop) >+ { >+ const selectedStop = gradientSlider.selectedStop; >+ if (selectedStop && !this._editingColor) { >+ this._element.appendChild(this._colorPicker.element); >+ this._element.classList.add("editing-color"); >+ this._colorPicker.color = selectedStop.color; >+ this._editingColor = true; >+ } else if (!selectedStop) { >+ this._colorPicker.element.remove(); >+ this._element.classList.remove("editing-color"); >+ this._editingColor = false; >+ } >+ >+ // Ensure the angle input is not focused since, if it were, it'd make a scrollbar appear as we >+ // animate the popover's frame to fit its new content. >+ this._angleInput.blur(); >+ >+ this.dispatchEventToListeners(WebInspector.GradientEditor.Event.ColorPickerToggled); >+ this.dispatchEventToListeners(WebInspector.GradientEditor.Event.GradientChanged, {gradient: this._gradient}); >+ } >+ >+ dragToAdjustControllerWasAdjustedByAmount(dragToAdjustController, amount) >+ { >+ const angleInputValue = parseFloat(this._angleInput.value); >+ if (isNaN(angleInputValue)) >+ return; >+ >+ let angle = angleInputValue + amount; >+ if (Math.round(angle) !== angle) >+ angle = angle.toFixed(1); >+ >+ this._angleInput.value = angle; >+ this._angleInputValueDidChange(angle); >+ } >+ >+ // Private >+ >+ _updateCSSClassForGradientType() >+ { >+ const isRadial = this._gradient instanceof WebInspector.RadialGradient; >+ this._element.classList.toggle("radial-gradient", isRadial); >+ >+ this.dispatchEventToListeners(WebInspector.GradientEditor.Event.ColorPickerToggled); >+ } >+ >+ _gradientTypeChanged(event) >+ { >+ const descriptor = this._gradientTypes[this._gradientTypePicker.value]; >+ if (!(this._gradient instanceof descriptor.type)) { >+ if (descriptor.type === WebInspector.LinearGradient) { >+ this._gradient = new WebInspector.LinearGradient(180, this._gradient.stops); >+ this._angleInput.value = "180\u00B0"; >+ } else >+ this._gradient = new WebInspector.RadialGradient("", this._gradient.stops); >+ >+ this._updateCSSClassForGradientType(); >+ } >+ this._gradient.repeats = descriptor.repeats; >+ >+ this.dispatchEventToListeners(WebInspector.GradientEditor.Event.GradientChanged, {gradient: this._gradient}); >+ } >+ >+ _colorPickerColorChanged(event) >+ { >+ this._gradientSlider.selectedStop.color = event.target.color; >+ this._gradientSlider.stops = this._gradient.stops; >+ >+ this.dispatchEventToListeners(WebInspector.GradientEditor.Event.GradientChanged, {gradient: this._gradient}); >+ } >+ >+ _angleChanged(event) >+ { >+ const angle = parseFloat(this._angleInput.value) || 0; >+ if (isNaN(angle)) >+ return; >+ >+ this._angleInputValueDidChange(angle); >+ } >+ >+ _angleInputValueDidChange(angle) >+ { >+ this._gradient.angle = angle; >+ const matches = this._angleInput.value.match(/\u00B0/g); >+ if (!matches || matches.length !== 1) { >+ const savedStart = this._angleInput.selectionStart; >+ this._angleInput.value = angle + "\u00B0"; >+ this._angleInput.selectionStart = savedStart; >+ this._angleInput.selectionEnd = savedStart; >+ } >+ >+ this.dispatchEventToListeners(WebInspector.GradientEditor.Event.GradientChanged, {gradient: this._gradient}); >+ } >+} >+ >+WebInspector.GradientEditor.Event = { >+ GradientChanged: "gradient-editor-gradient-changed", >+ ColorPickerToggled: "gradient-editor-color-picker-toggled" >+}; >diff --git a/Source/WebInspectorUI/UserInterface/Views/VisualStyleBackgroundPicker.css b/Source/WebInspectorUI/UserInterface/Views/VisualStyleBackgroundPicker.css >new file mode 100644 >index 0000000..5fbe439 >--- /dev/null >+++ b/Source/WebInspectorUI/UserInterface/Views/VisualStyleBackgroundPicker.css >@@ -0,0 +1,93 @@ >+/* >+ * Copyright (C) 2015 Devin Rousso <dcrousso+webkit@gmail.com>. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+.visual-style-property-container.background-picker > .visual-style-property-value-container { >+ display: flex; >+} >+ >+.visual-style-property-container.background-picker > .visual-style-property-value-container > .color-gradient-swatch { >+ display: none; >+ position: relative; >+ width: 38px; >+ height: 18px; >+ margin-top: 1px; >+ /* Make a checkered background for transparent colors to show against. */ >+ background-image: linear-gradient(to bottom, hsl(0, 0%, 80%), hsl(0, 0%, 80%)), >+ linear-gradient(to bottom, hsl(0, 0%, 80%), hsl(0, 0%, 80%)); >+ background-color: white; >+ background-size: 50%; >+ background-position: top left, bottom right; >+ background-repeat: no-repeat; >+ border: 1px solid hsla(0, 0%, 25%, 0.4); >+ border-radius: 4px; >+ overflow: hidden; >+ cursor: default; >+} >+ >+.visual-style-property-container.background-picker > .visual-style-property-value-container > .color-gradient-swatch:hover { >+ border-color: hsla(0, 0%, 25%, 0.8); >+} >+ >+.visual-style-property-container.background-picker > .visual-style-property-value-container > .color-gradient-swatch:active { >+ border-color: hsl(0, 0%, 25%); >+} >+ >+.visual-style-property-container.background-picker > .visual-style-property-value-container > .color-gradient-swatch > span { >+ position: absolute; >+ top: 0; >+ right: 0; >+ bottom: 0; >+ left: 0; >+} >+ >+.visual-style-property-container.background-picker > .visual-style-property-value-container.gradient-value > .color-gradient-swatch { >+ display: block; >+} >+ >+.visual-style-property-container.background-picker > .visual-style-property-value-container.gradient-value > .color-gradient-swatch + .value-input { >+ margin-left: -3px; >+ padding-left: 5px; >+ border-top-left-radius: 0; >+ border-bottom-left-radius: 0; >+ border-left: none; >+} >+ >+.visual-style-property-container.background-picker > .visual-style-property-value-container > .value-input { >+ margin: 1px 4px 3px 0; >+ padding: 0 3px; >+ border-radius: 4px; >+ border: solid 1px hsl(0, 0%, 83%); >+ text-align: left; >+ font-size: 10px; >+} >+ >+.visual-style-property-container.background-picker > .visual-style-property-value-container > .value-input[disabled] { >+ opacity: 0.7; >+ pointer-events: none; >+} >+ >+.visual-style-property-container.background-picker > .visual-style-property-value-container > .value-type-picker-select { >+ max-width: 170px; >+} >diff --git a/Source/WebInspectorUI/UserInterface/Views/VisualStyleBackgroundPicker.js b/Source/WebInspectorUI/UserInterface/Views/VisualStyleBackgroundPicker.js >new file mode 100644 >index 0000000..79d0c20 >--- /dev/null >+++ b/Source/WebInspectorUI/UserInterface/Views/VisualStyleBackgroundPicker.js >@@ -0,0 +1,261 @@ >+/* >+ * Copyright (C) 2015 Devin Rousso <dcrousso+webkit@gmail.com>. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+WebInspector.VisualStyleBackgroundPicker = class VisualStyleBackgroundPicker extends WebInspector.VisualStylePropertyEditor >+{ >+ constructor(propertyNames, text, possibleValues, layoutReversed) >+ { >+ super(propertyNames, text, possibleValues, null, "background-picker", layoutReversed); >+ >+ this._gradientSwatchElement = document.createElement("span"); >+ this._gradientSwatchElement.classList.add("color-gradient-swatch"); >+ this._gradientSwatchElement.title = WebInspector.UIString("Click to select a gradient"); >+ this._gradientSwatchElement.addEventListener("click", this._gradientSwatchClicked.bind(this)); >+ >+ let gradientSwatchInnerElement = document.createElement("span"); >+ this._gradientSwatchElement.appendChild(gradientSwatchInnerElement); >+ >+ this.contentElement.appendChild(this._gradientSwatchElement); >+ >+ this._valueInputElement = document.createElement("input"); >+ this._valueInputElement.classList.add("value-input"); >+ this._valueInputElement.type = "url"; >+ this._valueInputElement.placeholder = WebInspector.UIString("Enter a URL"); >+ this._valueInputElement.addEventListener("input", this._valueInputValueChanged.bind(this)); >+ this.contentElement.appendChild(this._valueInputElement); >+ >+ this._valueTypePickerElement = document.createElement("select"); >+ this._valueTypePickerElement.classList.add("value-type-picker-select"); >+ if (this._possibleValues.advanced) >+ this._valueTypePickerElement.title = WebInspector.UIString("Option-click to show all values"); >+ >+ let imageOption = document.createElement("option"); >+ imageOption.value = "url"; >+ imageOption.text = WebInspector.UIString("Image"); >+ this._valueTypePickerElement.appendChild(imageOption); >+ >+ let linearGradientOption = document.createElement("option"); >+ linearGradientOption.value = "linear-gradient"; >+ linearGradientOption.text = WebInspector.UIString("Linear Gradient"); >+ this._valueTypePickerElement.appendChild(linearGradientOption); >+ >+ let radialGradientOption = document.createElement("option"); >+ radialGradientOption.value = "radial-gradient"; >+ radialGradientOption.text = WebInspector.UIString("Radial Gradient"); >+ this._valueTypePickerElement.appendChild(radialGradientOption); >+ >+ let repeatingLinearGradientOption = document.createElement("option"); >+ repeatingLinearGradientOption.value = "repeating-linear-gradient"; >+ repeatingLinearGradientOption.text = WebInspector.UIString("Repeating Linear Gradient"); >+ this._valueTypePickerElement.appendChild(repeatingLinearGradientOption); >+ >+ let repeatingRadialGradientOption = document.createElement("option"); >+ repeatingRadialGradientOption.value = "repeating-radial-gradient"; >+ repeatingRadialGradientOption.text = WebInspector.UIString("Repeating Radial Gradient"); >+ this._valueTypePickerElement.appendChild(repeatingRadialGradientOption); >+ >+ this._valueTypePickerElement.appendChild(document.createElement("hr")); >+ >+ this._createValueOptions(this._possibleValues.basic); >+ this._advancedValuesElements = null; >+ >+ this._valueTypePickerElement.addEventListener("mousedown", this._keywordSelectMouseDown.bind(this)); >+ this._valueTypePickerElement.addEventListener("change", this._handleKeywordChanged.bind(this)); >+ this.contentElement.appendChild(this._valueTypePickerElement); >+ >+ this._currentType = "url"; >+ this._gradient = null; >+ >+ this._updateGradientSwatch(); >+ } >+ >+ // Public >+ >+ get value() >+ { >+ return this._valueInputElement.value; >+ } >+ >+ set value(value) >+ { >+ if (!value || !value.length || value === this.value) >+ return; >+ >+ const isKeyword = this.valueIsSupportedKeyword(value); >+ this._currentType = isKeyword ? value : value.substring(0, value.indexOf("(")); >+ this._updateValueInput(); >+ if (!isKeyword) >+ this._valueInputElement.value = value.substring(value.indexOf("(") + 1, value.length - 1); >+ >+ this._valueTypePickerElement.value = this._currentType; >+ >+ if (!this._currentType.includes("gradient")) >+ return; >+ >+ this._gradient = WebInspector.Gradient.fromString(value); >+ if (!this._gradient) >+ return; >+ >+ this._updateGradientSwatch(); >+ } >+ >+ get synthesizedValue() >+ { >+ if (this.valueIsSupportedKeyword(this._currentType)) >+ return this._currentType; >+ >+ return this._currentType + "(" + this.value + ")"; >+ } >+ >+ // Protected >+ >+ parseValue(text) >+ { >+ const validPrefixes = ["url", "linear-gradient", "radial-gradient", "repeating-linear-gradient", "repeating-radial-gradient"]; >+ return validPrefixes.some((item) => text.startsWith(item)) ? [text, text] : null; >+ } >+ >+ // Private >+ >+ _updateValueInput() >+ { >+ const supportedKeyword = this.valueIsSupportedKeyword(this._currentType); >+ const gradientValue = this._currentType.includes("gradient"); >+ this.contentElement.classList.toggle("gradient-value", !supportedKeyword && gradientValue); >+ this._valueInputElement.disabled = supportedKeyword; >+ if (supportedKeyword) { >+ this._valueInputElement.value = ""; >+ this._valueInputElement.placeholder = WebInspector.UIString("Using Keyword Value"); >+ } else { >+ if (this._currentType === "image") { >+ this._valueInputElement.type = "url"; >+ this._valueInputElement.placeholder = WebInspector.UIString("Enter a URL"); >+ } else if (gradientValue) { >+ this._valueInputElement.type = "text"; >+ this._valueInputElement.placeholder = WebInspector.UIString("Enter a Gradient"); >+ } >+ } >+ } >+ >+ _updateGradientSwatch() >+ { >+ this._gradientSwatchElement.firstChild.style.background = ""; >+ const value = this.synthesizedValue; >+ if (!value || value === this._currentType) >+ return; >+ >+ this._gradient = WebInspector.Gradient.fromString(value); >+ this._gradientSwatchElement.firstChild.style.background = this._gradient ? value : null; >+ } >+ >+ _gradientSwatchClicked(event) >+ { >+ let bounds = WebInspector.Rect.rectFromClientRect(this._gradientSwatchElement.getBoundingClientRect()); >+ let popover = new WebInspector.Popover(this); >+ >+ function handleColorPickerToggled(event) >+ { >+ popover.update(); >+ } >+ >+ let gradientEditor = new WebInspector.GradientEditor; >+ gradientEditor.addEventListener(WebInspector.GradientEditor.Event.GradientChanged, this._gradientEditorGradientChanged, this); >+ gradientEditor.addEventListener(WebInspector.GradientEditor.Event.ColorPickerToggled, handleColorPickerToggled, this); >+ >+ popover.content = gradientEditor.element; >+ popover.present(bounds.pad(2), [WebInspector.RectEdge.MIN_X]); >+ >+ gradientEditor.gradient = this._gradient; >+ } >+ >+ _gradientEditorGradientChanged(event) >+ { >+ this.value = event.data.gradient.toString(); >+ this._valueDidChange(); >+ } >+ >+ _valueInputValueChanged(event) >+ { >+ this._updateGradientSwatch(); >+ this._valueDidChange(); >+ } >+ >+ _keywordSelectMouseDown(event) >+ { >+ if (event.altKey) >+ this._addAdvancedValues(); >+ else if (!this._valueIsSupportedAdvancedKeyword()) >+ this._removeAdvancedValues(); >+ } >+ >+ _handleKeywordChanged(event) >+ { >+ this._currentType = this._valueTypePickerElement.value; >+ this._updateValueInput(); >+ this._updateGradientSwatch(); >+ this._valueDidChange(); >+ } >+ >+ _createValueOptions(values) >+ { >+ let addedElements = []; >+ for (let key in values) { >+ let option = document.createElement("option"); >+ option.value = key; >+ option.text = values[key]; >+ this._valueTypePickerElement.appendChild(option); >+ addedElements.push(option); >+ } >+ return addedElements; >+ } >+ >+ _addAdvancedValues() >+ { >+ if (this._advancedValuesElements) >+ return; >+ >+ this._valueTypePickerElement.appendChild(document.createElement("hr")); >+ this._advancedValuesElements = this._createValueOptions(this._possibleValues.advanced); >+ } >+ >+ _removeAdvancedValues() >+ { >+ if (!this._advancedValuesElements) >+ return; >+ >+ this._valueTypePickerElement.removeChild(this._advancedValuesElements[0].previousSibling); >+ for (let element of this._advancedValuesElements) >+ this._valueTypePickerElement.removeChild(element); >+ >+ this._advancedValuesElements = null; >+ } >+ >+ _toggleTabbingOfSelectableElements(disabled) >+ { >+ let tabIndex = disabled ? "-1" : null; >+ this._valueInputElement.tabIndex = tabIndex; >+ this._valueTypePickerElement.tabIndex = tabIndex; >+ } >+}; >diff --git a/Source/WebInspectorUI/UserInterface/Views/VisualStyleCommaSeparatedKeywordEditor.js b/Source/WebInspectorUI/UserInterface/Views/VisualStyleCommaSeparatedKeywordEditor.js >index 1e96016..0684964 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/VisualStyleCommaSeparatedKeywordEditor.js >+++ b/Source/WebInspectorUI/UserInterface/Views/VisualStyleCommaSeparatedKeywordEditor.js >@@ -100,9 +100,10 @@ WebInspector.VisualStyleCommaSeparatedKeywordEditor = class VisualStyleCommaSepa > return; > } > >- let values = commaSeparatedValue.split(/\s*,\s*(?![^\(]*\))/); >+ // It is necessary to add the beginning \) to ensure inner parenthesis are not matched. >+ let values = commaSeparatedValue.split(/\)\s*,\s*(?![^\(\)]*\))/); > for (let value of values) >- this._addCommaSeparatedKeyword(value); >+ this._addCommaSeparatedKeyword(value + (value.endsWith(")") ? "" : ")")); > > this._commaSeparatedKeywords.children[0].select(true); > } >diff --git a/Source/WebInspectorUI/UserInterface/Views/VisualStyleDetailsPanel.js b/Source/WebInspectorUI/UserInterface/Views/VisualStyleDetailsPanel.js >index 2ed76c1..0b0ab26 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/VisualStyleDetailsPanel.js >+++ b/Source/WebInspectorUI/UserInterface/Views/VisualStyleDetailsPanel.js >@@ -790,7 +790,7 @@ WebInspector.VisualStyleDetailsPanel = class VisualStyleDetailsPanel extends Web > > let backgroundImageRow = new WebInspector.DetailsSectionRow; > >- let backgroundImage = new WebInspector.VisualStyleURLInput("background-image", WebInspector.UIString("Image"), this._keywords.defaults.concat(["None"])); >+ let backgroundImage = new WebInspector.VisualStyleBackgroundPicker("background-image", WebInspector.UIString("Type"), this._keywords.defaults.concat(["None"])); > > backgroundImageRow.element.appendChild(backgroundImage.element); > >diff --git a/Source/WebInspectorUI/UserInterface/Views/VisualStylePropertyEditorLink.css b/Source/WebInspectorUI/UserInterface/Views/VisualStylePropertyEditorLink.css >index a3b4869..e16a31c 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/VisualStylePropertyEditorLink.css >+++ b/Source/WebInspectorUI/UserInterface/Views/VisualStylePropertyEditorLink.css >@@ -89,7 +89,7 @@ > > .visual-style-property-editor-link:not(.link-all) > .visual-style-property-editor-link-border { > width: 10px; >- top: -webkit-calc(50% - 1px); >+ top: 50%; > } > > .visual-style-property-editor-link:not(.link-all).linked > .visual-style-property-editor-link-border { >diff --git a/Source/WebInspectorUI/UserInterface/Views/VisualStyleURLInput.js b/Source/WebInspectorUI/UserInterface/Views/VisualStyleURLInput.js >deleted file mode 100644 >index 2587946..0000000 >--- a/Source/WebInspectorUI/UserInterface/Views/VisualStyleURLInput.js >+++ /dev/null >@@ -1,75 +0,0 @@ >-/* >- * Copyright (C) 2015 Apple Inc. All rights reserved. >- * >- * Redistribution and use in source and binary forms, with or without >- * modification, are permitted provided that the following conditions >- * are met: >- * 1. Redistributions of source code must retain the above copyright >- * notice, this list of conditions and the following disclaimer. >- * 2. Redistributions in binary form must reproduce the above copyright >- * notice, this list of conditions and the following disclaimer in the >- * documentation and/or other materials provided with the distribution. >- * >- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >- * THE POSSIBILITY OF SUCH DAMAGE. >- */ >- >-WebInspector.VisualStyleURLInput = class VisualStyleURLInput extends WebInspector.VisualStylePropertyEditor >-{ >- constructor(propertyNames, text, possibleValues, layoutReversed) >- { >- super(propertyNames, text, possibleValues, null, "url-input", layoutReversed); >- >- this._urlInputElement = document.createElement("input"); >- this._urlInputElement.type = "url"; >- this._urlInputElement.placeholder = WebInspector.UIString("Enter a URL"); >- this._urlInputElement.addEventListener("keyup", this._valueDidChange.bind(this)); >- this.contentElement.appendChild(this._urlInputElement); >- } >- >- // Public >- >- get value() >- { >- return this._urlInputElement.value; >- } >- >- set value(value) >- { >- if (value && value === this.value) >- return; >- >- this._urlInputElement.value = value; >- } >- >- get synthesizedValue() >- { >- let value = this.value; >- if (!value || !value.length) >- return null; >- >- if (this.valueIsSupportedKeyword(value)) >- return value; >- >- return "url(" + value + ")"; >- } >- >- // Protected >- >- parseValue(text) >- { >- if (this.valueIsSupportedKeyword(text)) >- return [text, text]; >- >- return /^(?:url\(\s*)([^\)]*)(?:\s*\)\s*;?)$/.exec(text); >- } >-};
Comment on attachment 265942 [details] Patch Clearing flags on attachment: 265942 Committed r192705: <http://trac.webkit.org/changeset/192705>
All reviewed patches have been landed. Closing bug.