Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(296)

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/components/Spectrum.js

Issue 2466123002: DevTools: reformat front-end code to match chromium style. (Closed)
Patch Set: all done Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2011 Brian Grinstead All rights reserved. 2 * Copyright (C) 2011 Brian Grinstead All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the 11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution. 12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived 14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission. 15 * from this software without specific prior written permission.
16 * 16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28
29 /** 28 /**
30 * @constructor 29 * @unrestricted
31 * @extends {WebInspector.VBox}
32 */ 30 */
33 WebInspector.Spectrum = function() 31 WebInspector.Spectrum = class extends WebInspector.VBox {
34 { 32 constructor() {
35 /** 33 /**
36 * @param {!Element} parentElement 34 * @param {!Element} parentElement
37 */ 35 */
38 function appendSwitcherIcon(parentElement) 36 function appendSwitcherIcon(parentElement) {
39 { 37 var icon = parentElement.createSVGChild('svg');
40 var icon = parentElement.createSVGChild("svg"); 38 icon.setAttribute('height', 16);
41 icon.setAttribute("height", 16); 39 icon.setAttribute('width', 16);
42 icon.setAttribute("width", 16); 40 var path = icon.createSVGChild('path');
43 var path = icon.createSVGChild("path"); 41 path.setAttribute('d', 'M5,6 L11,6 L8,2 Z M5,10 L11,10 L8,14 Z');
44 path.setAttribute("d", "M5,6 L11,6 L8,2 Z M5,10 L11,10 L8,14 Z"); 42 return icon;
45 return icon;
46 } 43 }
47 44
48 WebInspector.VBox.call(this, true); 45 super(true);
49 this.registerRequiredCSS("components/spectrum.css"); 46 this.registerRequiredCSS('components/spectrum.css');
50 this.contentElement.tabIndex = 0; 47 this.contentElement.tabIndex = 0;
51 this.setDefaultFocusedElement(this.contentElement); 48 this.setDefaultFocusedElement(this.contentElement);
52 49
53 this._colorElement = this.contentElement.createChild("div", "spectrum-color" ); 50 this._colorElement = this.contentElement.createChild('div', 'spectrum-color' );
54 this._colorDragElement = this._colorElement.createChild("div", "spectrum-sat fill").createChild("div", "spectrum-val fill").createChild("div", "spectrum-dra gger"); 51 this._colorDragElement = this._colorElement.createChild('div', 'spectrum-sat fill')
55 var contrastRatioSVG = this._colorElement.createSVGChild("svg", "spectrum-co ntrast-container fill"); 52 .createChild('div', 'spectrum-val fill')
56 this._contrastRatioLine = contrastRatioSVG.createSVGChild("path", "spectrum- contrast-line"); 53 .createChild('div', 'spectrum-dragger');
54 var contrastRatioSVG = this._colorElement.createSVGChild('svg', 'spectrum-co ntrast-container fill');
55 this._contrastRatioLine = contrastRatioSVG.createSVGChild('path', 'spectrum- contrast-line');
57 56
58 var toolbar = new WebInspector.Toolbar("spectrum-eye-dropper", this.contentE lement); 57 var toolbar = new WebInspector.Toolbar('spectrum-eye-dropper', this.contentE lement);
59 this._colorPickerButton = new WebInspector.ToolbarToggle(WebInspector.UIStri ng("Toggle color picker"), "eyedropper-toolbar-item"); 58 this._colorPickerButton =
59 new WebInspector.ToolbarToggle(WebInspector.UIString('Toggle color picke r'), 'eyedropper-toolbar-item');
60 this._colorPickerButton.setToggled(true); 60 this._colorPickerButton.setToggled(true);
61 this._colorPickerButton.addEventListener("click", this._toggleColorPicker.bi nd(this, undefined)); 61 this._colorPickerButton.addEventListener('click', this._toggleColorPicker.bi nd(this, undefined));
62 toolbar.appendToolbarItem(this._colorPickerButton); 62 toolbar.appendToolbarItem(this._colorPickerButton);
63 63
64 var swatchElement = this.contentElement.createChild("span", "swatch"); 64 var swatchElement = this.contentElement.createChild('span', 'swatch');
65 this._swatchInnerElement = swatchElement.createChild("span", "swatch-inner") ; 65 this._swatchInnerElement = swatchElement.createChild('span', 'swatch-inner') ;
66 66
67 this._hueElement = this.contentElement.createChild("div", "spectrum-hue"); 67 this._hueElement = this.contentElement.createChild('div', 'spectrum-hue');
68 this._hueSlider = this._hueElement.createChild("div", "spectrum-slider"); 68 this._hueSlider = this._hueElement.createChild('div', 'spectrum-slider');
69 this._alphaElement = this.contentElement.createChild("div", "spectrum-alpha" ); 69 this._alphaElement = this.contentElement.createChild('div', 'spectrum-alpha' );
70 this._alphaElementBackground = this._alphaElement.createChild("div", "spectr um-alpha-background"); 70 this._alphaElementBackground = this._alphaElement.createChild('div', 'spectr um-alpha-background');
71 this._alphaSlider = this._alphaElement.createChild("div", "spectrum-slider") ; 71 this._alphaSlider = this._alphaElement.createChild('div', 'spectrum-slider') ;
72 72
73 var displaySwitcher = this.contentElement.createChild("div", "spectrum-displ ay-switcher spectrum-switcher"); 73 var displaySwitcher = this.contentElement.createChild('div', 'spectrum-displ ay-switcher spectrum-switcher');
74 appendSwitcherIcon(displaySwitcher); 74 appendSwitcherIcon(displaySwitcher);
75 displaySwitcher.addEventListener("click", this._formatViewSwitch.bind(this)) ; 75 displaySwitcher.addEventListener('click', this._formatViewSwitch.bind(this)) ;
76 76
77 // RGBA/HSLA display. 77 // RGBA/HSLA display.
78 this._displayContainer = this.contentElement.createChild("div", "spectrum-te xt source-code"); 78 this._displayContainer = this.contentElement.createChild('div', 'spectrum-te xt source-code');
79 this._textValues = []; 79 this._textValues = [];
80 for (var i = 0; i < 4; ++i) { 80 for (var i = 0; i < 4; ++i) {
81 var inputValue = this._displayContainer.createChild("input", "spectrum-t ext-value"); 81 var inputValue = this._displayContainer.createChild('input', 'spectrum-tex t-value');
82 inputValue.maxLength = 4; 82 inputValue.maxLength = 4;
83 this._textValues.push(inputValue); 83 this._textValues.push(inputValue);
84 inputValue.addEventListener("keydown", this._inputChanged.bind(this), fa lse); 84 inputValue.addEventListener('keydown', this._inputChanged.bind(this), fals e);
85 inputValue.addEventListener("input", this._inputChanged.bind(this), fals e); 85 inputValue.addEventListener('input', this._inputChanged.bind(this), false) ;
86 inputValue.addEventListener("mousewheel", this._inputChanged.bind(this), false); 86 inputValue.addEventListener('mousewheel', this._inputChanged.bind(this), f alse);
87 } 87 }
88 88
89 this._textLabels = this._displayContainer.createChild("div", "spectrum-text- label"); 89 this._textLabels = this._displayContainer.createChild('div', 'spectrum-text- label');
90 90
91 // HEX display. 91 // HEX display.
92 this._hexContainer = this.contentElement.createChild("div", "spectrum-text s pectrum-text-hex source-code"); 92 this._hexContainer = this.contentElement.createChild('div', 'spectrum-text s pectrum-text-hex source-code');
93 this._hexValue = this._hexContainer.createChild("input", "spectrum-text-valu e"); 93 this._hexValue = this._hexContainer.createChild('input', 'spectrum-text-valu e');
94 this._hexValue.maxLength = 7; 94 this._hexValue.maxLength = 7;
95 this._hexValue.addEventListener("keydown", this._inputChanged.bind(this), fa lse); 95 this._hexValue.addEventListener('keydown', this._inputChanged.bind(this), fa lse);
96 this._hexValue.addEventListener("input", this._inputChanged.bind(this), fals e); 96 this._hexValue.addEventListener('input', this._inputChanged.bind(this), fals e);
97 this._hexValue.addEventListener("mousewheel", this._inputChanged.bind(this), false); 97 this._hexValue.addEventListener('mousewheel', this._inputChanged.bind(this), false);
98 98
99 var label = this._hexContainer.createChild("div", "spectrum-text-label"); 99 var label = this._hexContainer.createChild('div', 'spectrum-text-label');
100 label.textContent = "HEX"; 100 label.textContent = 'HEX';
101 101
102 WebInspector.installDragHandle(this._hueElement, dragStart.bind(this, positi onHue.bind(this)), positionHue.bind(this), null, "default"); 102 WebInspector.installDragHandle(
103 WebInspector.installDragHandle(this._alphaElement, dragStart.bind(this, posi tionAlpha.bind(this)), positionAlpha.bind(this), null, "default"); 103 this._hueElement, dragStart.bind(this, positionHue.bind(this)), position Hue.bind(this), null, 'default');
104 WebInspector.installDragHandle(this._colorElement, dragStart.bind(this, posi tionColor.bind(this)), positionColor.bind(this), null, "default"); 104 WebInspector.installDragHandle(
105 this._alphaElement, dragStart.bind(this, positionAlpha.bind(this)), posi tionAlpha.bind(this), null, 'default');
106 WebInspector.installDragHandle(
107 this._colorElement, dragStart.bind(this, positionColor.bind(this)), posi tionColor.bind(this), null, 'default');
105 108
106 this.element.classList.add("palettes-enabled"); 109 this.element.classList.add('palettes-enabled');
107 /** @type {!Map.<string, !WebInspector.Spectrum.Palette>} */ 110 /** @type {!Map.<string, !WebInspector.Spectrum.Palette>} */
108 this._palettes = new Map(); 111 this._palettes = new Map();
109 this._palettePanel = this.contentElement.createChild("div", "palette-panel") ; 112 this._palettePanel = this.contentElement.createChild('div', 'palette-panel') ;
110 this._palettePanelShowing = false; 113 this._palettePanelShowing = false;
111 this._paletteContainer = this.contentElement.createChild("div", "spectrum-pa lette"); 114 this._paletteContainer = this.contentElement.createChild('div', 'spectrum-pa lette');
112 this._paletteContainer.addEventListener("contextmenu", this._showPaletteColo rContextMenu.bind(this, -1)); 115 this._paletteContainer.addEventListener('contextmenu', this._showPaletteColo rContextMenu.bind(this, -1));
113 this._shadesContainer = this.contentElement.createChild("div", "palette-colo r-shades hidden"); 116 this._shadesContainer = this.contentElement.createChild('div', 'palette-colo r-shades hidden');
114 WebInspector.installDragHandle(this._paletteContainer, this._paletteDragStar t.bind(this), this._paletteDrag.bind(this), this._paletteDragEnd.bind(this), "de fault"); 117 WebInspector.installDragHandle(
115 var paletteSwitcher = this.contentElement.createChild("div", "spectrum-palet te-switcher spectrum-switcher"); 118 this._paletteContainer, this._paletteDragStart.bind(this), this._palette Drag.bind(this),
119 this._paletteDragEnd.bind(this), 'default');
120 var paletteSwitcher = this.contentElement.createChild('div', 'spectrum-palet te-switcher spectrum-switcher');
116 appendSwitcherIcon(paletteSwitcher); 121 appendSwitcherIcon(paletteSwitcher);
117 paletteSwitcher.addEventListener("click", this._togglePalettePanel.bind(this , true)); 122 paletteSwitcher.addEventListener('click', this._togglePalettePanel.bind(this , true));
118 123
119 this._deleteIconToolbar = new WebInspector.Toolbar("delete-color-toolbar"); 124 this._deleteIconToolbar = new WebInspector.Toolbar('delete-color-toolbar');
120 this._deleteButton = new WebInspector.ToolbarButton("", "garbage-collect-too lbar-item"); 125 this._deleteButton = new WebInspector.ToolbarButton('', 'garbage-collect-too lbar-item');
121 this._deleteIconToolbar.appendToolbarItem(this._deleteButton); 126 this._deleteIconToolbar.appendToolbarItem(this._deleteButton);
122 127
123 var overlay = this.contentElement.createChild("div", "spectrum-overlay fill" ); 128 var overlay = this.contentElement.createChild('div', 'spectrum-overlay fill' );
124 overlay.addEventListener("click", this._togglePalettePanel.bind(this, false) ); 129 overlay.addEventListener('click', this._togglePalettePanel.bind(this, false) );
125 130
126 this._addColorToolbar = new WebInspector.Toolbar("add-color-toolbar"); 131 this._addColorToolbar = new WebInspector.Toolbar('add-color-toolbar');
127 var addColorButton = new WebInspector.ToolbarButton(WebInspector.UIString("A dd to palette"), "add-toolbar-item"); 132 var addColorButton = new WebInspector.ToolbarButton(WebInspector.UIString('A dd to palette'), 'add-toolbar-item');
128 addColorButton.addEventListener("click", this._addColorToCustomPalette.bind( this)); 133 addColorButton.addEventListener('click', this._addColorToCustomPalette.bind( this));
129 this._addColorToolbar.appendToolbarItem(addColorButton); 134 this._addColorToolbar.appendToolbarItem(addColorButton);
130 135
131 this._loadPalettes(); 136 this._loadPalettes();
132 new WebInspector.Spectrum.PaletteGenerator(this._generatedPaletteLoaded.bind (this)); 137 new WebInspector.Spectrum.PaletteGenerator(this._generatedPaletteLoaded.bind (this));
133 138
134 /** 139 /**
135 * @param {function(!Event)} callback 140 * @param {function(!Event)} callback
136 * @param {!Event} event 141 * @param {!Event} event
137 * @return {boolean} 142 * @return {boolean}
138 * @this {WebInspector.Spectrum} 143 * @this {WebInspector.Spectrum}
139 */ 144 */
140 function dragStart(callback, event) 145 function dragStart(callback, event) {
141 { 146 this._hueAlphaLeft = this._hueElement.totalOffsetLeft();
142 this._hueAlphaLeft = this._hueElement.totalOffsetLeft(); 147 this._colorOffset = this._colorElement.totalOffset();
143 this._colorOffset = this._colorElement.totalOffset(); 148 callback(event);
144 callback(event); 149 return true;
145 return true;
146 } 150 }
147 151
148 /** 152 /**
149 * @param {!Event} event 153 * @param {!Event} event
150 * @this {WebInspector.Spectrum} 154 * @this {WebInspector.Spectrum}
151 */ 155 */
152 function positionHue(event) 156 function positionHue(event) {
153 { 157 var hsva = this._hsv.slice();
154 var hsva = this._hsv.slice(); 158 hsva[0] = Number.constrain(1 - (event.x - this._hueAlphaLeft) / this._hueA lphaWidth, 0, 1);
155 hsva[0] = Number.constrain(1 - (event.x - this._hueAlphaLeft) / this._hu eAlphaWidth, 0, 1); 159 this._innerSetColor(hsva, '', undefined, WebInspector.Spectrum._ChangeSour ce.Other);
156 this._innerSetColor(hsva, "", undefined, WebInspector.Spectrum._ChangeS ource.Other);
157 } 160 }
158 161
159 /** 162 /**
160 * @param {!Event} event 163 * @param {!Event} event
161 * @this {WebInspector.Spectrum} 164 * @this {WebInspector.Spectrum}
162 */ 165 */
163 function positionAlpha(event) 166 function positionAlpha(event) {
164 { 167 var newAlpha = Math.round((event.x - this._hueAlphaLeft) / this._hueAlphaW idth * 100) / 100;
165 var newAlpha = Math.round((event.x - this._hueAlphaLeft) / this._hueAlph aWidth * 100) / 100; 168 var hsva = this._hsv.slice();
166 var hsva = this._hsv.slice(); 169 hsva[3] = Number.constrain(newAlpha, 0, 1);
167 hsva[3] = Number.constrain(newAlpha, 0, 1); 170 var colorFormat = undefined;
168 var colorFormat = undefined; 171 if (hsva[3] !== 1 && (this._colorFormat === WebInspector.Color.Format.Shor tHEX ||
169 if (hsva[3] !== 1 && (this._colorFormat === WebInspector.Color.Format.Sh ortHEX || this._colorFormat === WebInspector.Color.Format.HEX || this._colorForm at === WebInspector.Color.Format.Nickname)) 172 this._colorFormat === WebInspector.Color.Format.HEX ||
170 colorFormat = WebInspector.Color.Format.RGB; 173 this._colorFormat === WebInspector.Color.Format.Nick name))
171 this._innerSetColor(hsva, "", colorFormat, WebInspector.Spectrum._Change Source.Other); 174 colorFormat = WebInspector.Color.Format.RGB;
175 this._innerSetColor(hsva, '', colorFormat, WebInspector.Spectrum._ChangeSo urce.Other);
172 } 176 }
173 177
174 /** 178 /**
175 * @param {!Event} event 179 * @param {!Event} event
176 * @this {WebInspector.Spectrum} 180 * @this {WebInspector.Spectrum}
177 */ 181 */
178 function positionColor(event) 182 function positionColor(event) {
179 { 183 var hsva = this._hsv.slice();
180 var hsva = this._hsv.slice(); 184 hsva[1] = Number.constrain((event.x - this._colorOffset.left) / this.dragW idth, 0, 1);
181 hsva[1] = Number.constrain((event.x - this._colorOffset.left) / this.dra gWidth, 0, 1); 185 hsva[2] = Number.constrain(1 - (event.y - this._colorOffset.top) / this.dr agHeight, 0, 1);
182 hsva[2] = Number.constrain(1 - (event.y - this._colorOffset.top) / this. dragHeight, 0, 1); 186 this._innerSetColor(hsva, '', undefined, WebInspector.Spectrum._ChangeSour ce.Other);
183 this._innerSetColor(hsva, "", undefined, WebInspector.Spectrum._ChangeS ource.Other); 187 }
184 } 188 }
189
190 _updatePalettePanel() {
191 this._palettePanel.removeChildren();
192 var title = this._palettePanel.createChild('div', 'palette-title');
193 title.textContent = WebInspector.UIString('Color Palettes');
194 var toolbar = new WebInspector.Toolbar('', this._palettePanel);
195 var closeButton = new WebInspector.ToolbarButton('Return to color picker', ' delete-toolbar-item');
196 closeButton.addEventListener('click', this._togglePalettePanel.bind(this, fa lse));
197 toolbar.appendToolbarItem(closeButton);
198 for (var palette of this._palettes.values())
199 this._palettePanel.appendChild(this._createPreviewPaletteElement(palette)) ;
200 }
201
202 /**
203 * @param {boolean} show
204 */
205 _togglePalettePanel(show) {
206 if (this._palettePanelShowing === show)
207 return;
208 if (show)
209 this._updatePalettePanel();
210 this._focus();
211 this._palettePanelShowing = show;
212 this.contentElement.classList.toggle('palette-panel-showing', show);
213 }
214
215 _focus() {
216 if (this.isShowing())
217 this.contentElement.focus();
218 }
219
220 /**
221 * @param {string} colorText
222 * @param {number=} animationDelay
223 * @return {!Element}
224 */
225 _createPaletteColor(colorText, animationDelay) {
226 var element = createElementWithClass('div', 'spectrum-palette-color');
227 element.style.background = String.sprintf('linear-gradient(%s, %s), url(Imag es/checker.png)', colorText, colorText);
228 if (animationDelay)
229 element.animate([{opacity: 0}, {opacity: 1}], {duration: 100, delay: anima tionDelay, fill: 'backwards'});
230 element.title = colorText;
231 return element;
232 }
233
234 /**
235 * @param {!WebInspector.Spectrum.Palette} palette
236 * @param {boolean} animate
237 * @param {!Event=} event
238 */
239 _showPalette(palette, animate, event) {
240 this._resizeForSelectedPalette();
241 this._paletteContainer.removeChildren();
242 for (var i = 0; i < palette.colors.length; i++) {
243 var animationDelay = animate ? i * 100 / palette.colors.length : 0;
244 var colorElement = this._createPaletteColor(palette.colors[i], animationDe lay);
245 colorElement.addEventListener(
246 'mousedown', this._paletteColorSelected.bind(this, palette.colors[i], palette.matchUserFormat));
247 if (palette.mutable) {
248 colorElement.__mutable = true;
249 colorElement.__color = palette.colors[i];
250 colorElement.addEventListener('contextmenu', this._showPaletteColorConte xtMenu.bind(this, i));
251 } else if (palette === WebInspector.Spectrum.MaterialPalette) {
252 colorElement.classList.add('has-material-shades');
253 var shadow = colorElement.createChild('div', 'spectrum-palette-color spe ctrum-palette-color-shadow');
254 shadow.style.background = palette.colors[i];
255 shadow = colorElement.createChild('div', 'spectrum-palette-color spectru m-palette-color-shadow');
256 shadow.style.background = palette.colors[i];
257 colorElement.title = WebInspector.UIString(palette.colors[i] + '. Long-c lick to show alternate shades.');
258 new WebInspector.LongClickController(
259 colorElement, this._showLightnessShades.bind(this, colorElement, pal ette.colors[i]));
260 }
261 this._paletteContainer.appendChild(colorElement);
262 }
263 this._paletteContainerMutable = palette.mutable;
264
265 var numItems = palette.colors.length;
266 if (palette.mutable)
267 numItems++;
268 if (palette.mutable) {
269 this._paletteContainer.appendChild(this._addColorToolbar.element);
270 this._paletteContainer.appendChild(this._deleteIconToolbar.element);
271 } else {
272 this._addColorToolbar.element.remove();
273 this._deleteIconToolbar.element.remove();
274 }
275
276 this._togglePalettePanel(false);
277 this._focus();
278 }
279
280 /**
281 * @param {!Element} colorElement
282 * @param {string} colorText
283 * @param {!Event} event
284 */
285 _showLightnessShades(colorElement, colorText, event) {
286 /**
287 * @param {!Element} element
288 * @this {!WebInspector.Spectrum}
289 */
290 function closeLightnessShades(element) {
291 this._shadesContainer.classList.add('hidden');
292 element.classList.remove('spectrum-shades-shown');
293 this._shadesContainer.ownerDocument.removeEventListener('mousedown', this. _shadesCloseHandler, true);
294 delete this._shadesCloseHandler;
295 }
296
297 if (this._shadesCloseHandler)
298 this._shadesCloseHandler();
299
300 this._shadesContainer.classList.remove('hidden');
301 this._shadesContainer.removeChildren();
302 this._shadesContainer.animate(
303 [{transform: 'scaleY(0)', opacity: '0'}, {transform: 'scaleY(1)', opacit y: '1'}],
304 {duration: 200, easing: 'cubic-bezier(0.4, 0, 0.2, 1)'});
305 this._shadesContainer.style.top = colorElement.offsetTop + colorElement.pare ntElement.offsetTop + 'px';
306 this._shadesContainer.style.left = colorElement.offsetLeft + 'px';
307 colorElement.classList.add('spectrum-shades-shown');
308
309 var shades = WebInspector.Spectrum.MaterialPaletteShades[colorText];
310 for (var i = shades.length - 1; i >= 0; i--) {
311 var shadeElement = this._createPaletteColor(shades[i], i * 200 / shades.le ngth + 100);
312 shadeElement.addEventListener('mousedown', this._paletteColorSelected.bind (this, shades[i], false));
313 this._shadesContainer.appendChild(shadeElement);
314 }
315
316 this._shadesContainer.focus();
317 this._shadesCloseHandler = closeLightnessShades.bind(this, colorElement);
318 this._shadesContainer.ownerDocument.addEventListener('mousedown', this._shad esCloseHandler, true);
319 }
320
321 /**
322 * @param {!Event} e
323 * @return {number}
324 */
325 _slotIndexForEvent(e) {
326 var localX = e.pageX - this._paletteContainer.totalOffsetLeft();
327 var localY = e.pageY - this._paletteContainer.totalOffsetTop();
328 var col =
329 Math.min(localX / WebInspector.Spectrum._colorChipSize | 0, WebInspector .Spectrum._itemsPerPaletteRow - 1);
330 var row = (localY / WebInspector.Spectrum._colorChipSize) | 0;
331 return Math.min(
332 row * WebInspector.Spectrum._itemsPerPaletteRow + col, this._customPalet teSetting.get().colors.length - 1);
333 }
334
335 /**
336 * @param {!Event} e
337 * @return {boolean}
338 */
339 _isDraggingToBin(e) {
340 return e.pageX > this._deleteIconToolbar.element.totalOffsetLeft();
341 }
342
343 /**
344 * @param {!Event} e
345 * @return {boolean}
346 */
347 _paletteDragStart(e) {
348 var element = e.deepElementFromPoint();
349 if (!element || !element.__mutable)
350 return false;
351
352 var index = this._slotIndexForEvent(e);
353 this._dragElement = element;
354 this._dragHotSpotX =
355 e.pageX - (index % WebInspector.Spectrum._itemsPerPaletteRow) * WebInspe ctor.Spectrum._colorChipSize;
356 this._dragHotSpotY =
357 e.pageY - (index / WebInspector.Spectrum._itemsPerPaletteRow | 0) * WebI nspector.Spectrum._colorChipSize;
358 return true;
359 }
360
361 /**
362 * @param {!Event} e
363 */
364 _paletteDrag(e) {
365 if (e.pageX < this._paletteContainer.totalOffsetLeft() || e.pageY < this._pa letteContainer.totalOffsetTop())
366 return;
367 var newIndex = this._slotIndexForEvent(e);
368 var offsetX =
369 e.pageX - (newIndex % WebInspector.Spectrum._itemsPerPaletteRow) * WebIn spector.Spectrum._colorChipSize;
370 var offsetY =
371 e.pageY - (newIndex / WebInspector.Spectrum._itemsPerPaletteRow | 0) * W ebInspector.Spectrum._colorChipSize;
372
373 var isDeleting = this._isDraggingToBin(e);
374 this._deleteIconToolbar.element.classList.add('dragging');
375 this._deleteIconToolbar.element.classList.toggle('delete-color-toolbar-activ e', isDeleting);
376 var dragElementTransform =
377 'translateX(' + (offsetX - this._dragHotSpotX) + 'px) translateY(' + (of fsetY - this._dragHotSpotY) + 'px)';
378 this._dragElement.style.transform = isDeleting ? dragElementTransform + ' sc ale(0.8)' : dragElementTransform;
379 var children = Array.prototype.slice.call(this._paletteContainer.children);
380 var index = children.indexOf(this._dragElement);
381 /** @type {!Map.<!Element, {left: number, top: number}>} */
382 var swatchOffsets = new Map();
383 for (var swatch of children)
384 swatchOffsets.set(swatch, swatch.totalOffset());
385
386 if (index !== newIndex)
387 this._paletteContainer.insertBefore(this._dragElement, children[newIndex > index ? newIndex + 1 : newIndex]);
388
389 for (var swatch of children) {
390 if (swatch === this._dragElement)
391 continue;
392 var before = swatchOffsets.get(swatch);
393 var after = swatch.totalOffset();
394 if (before.left !== after.left || before.top !== after.top) {
395 swatch.animate(
396 [
397 {
398 transform:
399 'translateX(' + (before.left - after.left) + 'px) translateY (' + (before.top - after.top) + 'px)'
400 },
401 {transform: 'none'}
402 ],
403 {duration: 100, easing: 'cubic-bezier(0, 0, 0.2, 1)'});
404 }
405 }
406 }
407
408 /**
409 * @param {!Event} e
410 */
411 _paletteDragEnd(e) {
412 if (this._isDraggingToBin(e))
413 this._dragElement.remove();
414 this._dragElement.style.removeProperty('transform');
415 var children = this._paletteContainer.children;
416 var colors = [];
417 for (var i = 0; i < children.length; ++i) {
418 if (children[i].__color)
419 colors.push(children[i].__color);
420 }
421 var palette = this._customPaletteSetting.get();
422 palette.colors = colors;
423 this._customPaletteSetting.set(palette);
424 this._showPalette(this._customPaletteSetting.get(), false);
425
426 this._deleteIconToolbar.element.classList.remove('dragging');
427 this._deleteIconToolbar.element.classList.remove('delete-color-toolbar-activ e');
428 }
429
430 _loadPalettes() {
431 this._palettes.set(WebInspector.Spectrum.MaterialPalette.title, WebInspector .Spectrum.MaterialPalette);
432 /** @type {!WebInspector.Spectrum.Palette} */
433 var defaultCustomPalette = {title: 'Custom', colors: [], mutable: true};
434 this._customPaletteSetting = WebInspector.settings.createSetting('customColo rPalette', defaultCustomPalette);
435 this._palettes.set(this._customPaletteSetting.get().title, this._customPalet teSetting.get());
436
437 this._selectedColorPalette =
438 WebInspector.settings.createSetting('selectedColorPalette', WebInspector .Spectrum.GeneratedPaletteTitle);
439 var palette = this._palettes.get(this._selectedColorPalette.get());
440 if (palette)
441 this._showPalette(palette, true);
442 }
443
444 /**
445 * @param {!WebInspector.Spectrum.Palette} generatedPalette
446 */
447 _generatedPaletteLoaded(generatedPalette) {
448 if (generatedPalette.colors.length)
449 this._palettes.set(generatedPalette.title, generatedPalette);
450 if (this._selectedColorPalette.get() !== generatedPalette.title) {
451 return;
452 } else if (!generatedPalette.colors.length) {
453 this._paletteSelected(WebInspector.Spectrum.MaterialPalette);
454 return;
455 }
456 this._showPalette(generatedPalette, true);
457 }
458
459 /**
460 * @param {!WebInspector.Spectrum.Palette} palette
461 * @return {!Element}
462 */
463 _createPreviewPaletteElement(palette) {
464 var colorsPerPreviewRow = 5;
465 var previewElement = createElementWithClass('div', 'palette-preview');
466 var titleElement = previewElement.createChild('div', 'palette-preview-title' );
467 titleElement.textContent = palette.title;
468 for (var i = 0; i < colorsPerPreviewRow && i < palette.colors.length; i++)
469 previewElement.appendChild(this._createPaletteColor(palette.colors[i]));
470 for (; i < colorsPerPreviewRow; i++)
471 previewElement.createChild('div', 'spectrum-palette-color empty-color');
472 previewElement.addEventListener('click', this._paletteSelected.bind(this, pa lette));
473 return previewElement;
474 }
475
476 /**
477 * @param {!WebInspector.Spectrum.Palette} palette
478 */
479 _paletteSelected(palette) {
480 this._selectedColorPalette.set(palette.title);
481 this._showPalette(palette, true);
482 }
483
484 _resizeForSelectedPalette() {
485 var palette = this._palettes.get(this._selectedColorPalette.get());
486 if (!palette)
487 return;
488 var numColors = palette.colors.length;
489 if (palette === this._customPaletteSetting.get())
490 numColors++;
491 var rowsNeeded = Math.max(1, Math.ceil(numColors / WebInspector.Spectrum._it emsPerPaletteRow));
492 if (this._numPaletteRowsShown === rowsNeeded)
493 return;
494 this._numPaletteRowsShown = rowsNeeded;
495 var paletteColorHeight = 12;
496 var paletteMargin = 12;
497 var paletteTop = 235;
498 this.element.style.height = (paletteTop + paletteMargin + (paletteColorHeigh t + paletteMargin) * rowsNeeded) + 'px';
499 this.dispatchEventToListeners(WebInspector.Spectrum.Events.SizeChanged);
500 }
501
502 /**
503 * @param {string} colorText
504 * @param {boolean} matchUserFormat
505 */
506 _paletteColorSelected(colorText, matchUserFormat) {
507 var color = WebInspector.Color.parse(colorText);
508 if (!color)
509 return;
510 this._innerSetColor(
511 color.hsva(), colorText, matchUserFormat ? this._colorFormat : color.for mat(),
512 WebInspector.Spectrum._ChangeSource.Other);
513 }
514
515 _addColorToCustomPalette() {
516 var palette = this._customPaletteSetting.get();
517 palette.colors.push(this.colorString());
518 this._customPaletteSetting.set(palette);
519 this._showPalette(this._customPaletteSetting.get(), false);
520 }
521
522 /**
523 * @param {number} colorIndex
524 * @param {!Event} event
525 */
526 _showPaletteColorContextMenu(colorIndex, event) {
527 if (!this._paletteContainerMutable)
528 return;
529 var contextMenu = new WebInspector.ContextMenu(event);
530 if (colorIndex !== -1) {
531 contextMenu.appendItem(
532 WebInspector.UIString('Remove color'), this._deletePaletteColors.bind( this, colorIndex, false));
533 contextMenu.appendItem(
534 WebInspector.UIString('Remove all to the right'), this._deletePaletteC olors.bind(this, colorIndex, true));
535 }
536 contextMenu.appendItem(WebInspector.UIString('Clear palette'), this._deleteP aletteColors.bind(this, -1, true));
537 contextMenu.show();
538 }
539
540 /**
541 * @param {number} colorIndex
542 * @param {boolean} toRight
543 */
544 _deletePaletteColors(colorIndex, toRight) {
545 var palette = this._customPaletteSetting.get();
546 if (toRight)
547 palette.colors.splice(colorIndex + 1, palette.colors.length - colorIndex - 1);
548 else
549 palette.colors.splice(colorIndex, 1);
550 this._customPaletteSetting.set(palette);
551 this._showPalette(this._customPaletteSetting.get(), false);
552 }
553
554 /**
555 * @param {!WebInspector.Color} color
556 * @param {string} colorFormat
557 */
558 setColor(color, colorFormat) {
559 this._originalFormat = colorFormat;
560 this._innerSetColor(color.hsva(), '', colorFormat, WebInspector.Spectrum._Ch angeSource.Model);
561 }
562
563 /**
564 * @param {!Array<number>|undefined} hsva
565 * @param {string|undefined} colorString
566 * @param {string|undefined} colorFormat
567 * @param {string} changeSource
568 */
569 _innerSetColor(hsva, colorString, colorFormat, changeSource) {
570 if (hsva !== undefined)
571 this._hsv = hsva;
572 if (colorString !== undefined)
573 this._colorString = colorString;
574 if (colorFormat !== undefined) {
575 console.assert(colorFormat !== WebInspector.Color.Format.Original, 'Spectr um\'s color format cannot be Original');
576 if (colorFormat === WebInspector.Color.Format.RGBA)
577 colorFormat = WebInspector.Color.Format.RGB;
578 else if (colorFormat === WebInspector.Color.Format.HSLA)
579 colorFormat = WebInspector.Color.Format.HSL;
580 this._colorFormat = colorFormat;
581 }
582
583 this._updateHelperLocations();
584 this._updateUI();
585
586 if (changeSource !== WebInspector.Spectrum._ChangeSource.Input)
587 this._updateInput();
588 if (changeSource !== WebInspector.Spectrum._ChangeSource.Model)
589 this.dispatchEventToListeners(WebInspector.Spectrum.Events.ColorChanged, t his.colorString());
590 }
591
592 /**
593 * @param {!WebInspector.Color} color
594 */
595 setContrastColor(color) {
596 this._contrastColor = color;
597 this._updateUI();
598 }
599
600 /**
601 * @return {!WebInspector.Color}
602 */
603 _color() {
604 return WebInspector.Color.fromHSVA(this._hsv);
605 }
606
607 /**
608 * @return {string}
609 */
610 colorString() {
611 if (this._colorString)
612 return this._colorString;
613 var cf = WebInspector.Color.Format;
614 var color = this._color();
615 var colorString = color.asString(this._colorFormat);
616 if (colorString)
617 return colorString;
618
619 if (this._colorFormat === cf.Nickname || this._colorFormat === cf.ShortHEX) {
620 colorString = color.asString(cf.HEX);
621 if (colorString)
622 return colorString;
623 }
624
625 console.assert(color.hasAlpha());
626 return this._colorFormat === cf.HSL ? /** @type {string} */ (color.asString( cf.HSLA)) :
627 /** @type {string} */ (color.asString( cf.RGBA));
628 }
629
630 _updateHelperLocations() {
631 var h = this._hsv[0];
632 var s = this._hsv[1];
633 var v = this._hsv[2];
634 var alpha = this._hsv[3];
635
636 // Where to show the little circle that displays your current selected color .
637 var dragX = s * this.dragWidth;
638 var dragY = this.dragHeight - (v * this.dragHeight);
639
640 dragX = Math.max(
641 -this._colorDragElementHeight,
642 Math.min(this.dragWidth - this._colorDragElementHeight, dragX - this._co lorDragElementHeight));
643 dragY = Math.max(
644 -this._colorDragElementHeight,
645 Math.min(this.dragHeight - this._colorDragElementHeight, dragY - this._c olorDragElementHeight));
646
647 this._colorDragElement.positionAt(dragX, dragY);
648
649 // Where to show the bar that displays your current selected hue.
650 var hueSlideX = (1 - h) * this._hueAlphaWidth - this.slideHelperWidth;
651 this._hueSlider.style.left = hueSlideX + 'px';
652 var alphaSlideX = alpha * this._hueAlphaWidth - this.slideHelperWidth;
653 this._alphaSlider.style.left = alphaSlideX + 'px';
654 }
655
656 _updateInput() {
657 var cf = WebInspector.Color.Format;
658 if (this._colorFormat === cf.HEX || this._colorFormat === cf.ShortHEX || thi s._colorFormat === cf.Nickname) {
659 this._hexContainer.hidden = false;
660 this._displayContainer.hidden = true;
661 if (this._colorFormat === cf.ShortHEX && this._color().canBeShortHex())
662 this._hexValue.value = this._color().asString(cf.ShortHEX);
663 else
664 this._hexValue.value = this._color().asString(cf.HEX);
665 } else {
666 // RGBA, HSLA display.
667 this._hexContainer.hidden = true;
668 this._displayContainer.hidden = false;
669 var isRgb = this._colorFormat === cf.RGB;
670 this._textLabels.textContent = isRgb ? 'RGBA' : 'HSLA';
671 var colorValues = isRgb ? this._color().canonicalRGBA() : this._color().ca nonicalHSLA();
672 for (var i = 0; i < 3; ++i) {
673 this._textValues[i].value = colorValues[i];
674 if (!isRgb && (i === 1 || i === 2))
675 this._textValues[i].value += '%';
676 }
677 this._textValues[3].value = Math.round(colorValues[3] * 100) / 100;
678 }
679 }
680
681 /**
682 * @param {number} requiredContrast
683 */
684 _drawContrastRatioLine(requiredContrast) {
685 if (!this._contrastColor || !this.dragWidth || !this.dragHeight)
686 return;
687
688 /** const */ var width = this.dragWidth;
689 /** const */ var height = this.dragHeight;
690 /** const */ var dS = 0.02;
691 /** const */ var epsilon = 0.002;
692 /** const */ var H = 0;
693 /** const */ var S = 1;
694 /** const */ var V = 2;
695 /** const */ var A = 3;
696
697 var fgRGBA = [];
698 WebInspector.Color.hsva2rgba(this._hsv, fgRGBA);
699 var fgLuminance = WebInspector.Color.luminance(fgRGBA);
700 var bgRGBA = this._contrastColor.rgba();
701 var bgLuminance = WebInspector.Color.luminance(bgRGBA);
702 var fgIsLighter = fgLuminance > bgLuminance;
703 var desiredLuminance = WebInspector.Color.desiredLuminance(bgLuminance, requ iredContrast, fgIsLighter);
704
705 var lastV = this._hsv[V];
706 var currentSlope = 0;
707 var candidateHSVA = [this._hsv[H], 0, 0, this._hsv[A]];
708 var pathBuilder = [];
709 var candidateRGBA = [];
710 WebInspector.Color.hsva2rgba(candidateHSVA, candidateRGBA);
711 var blendedRGBA = [];
712 WebInspector.Color.blendColors(candidateRGBA, bgRGBA, blendedRGBA);
713
714 /**
715 * Approach the desired contrast ratio by modifying the given component
716 * from the given starting value.
717 * @param {number} index
718 * @param {number} x
719 * @param {boolean} onAxis
720 * @return {?number}
721 */
722 function approach(index, x, onAxis) {
723 while (0 <= x && x <= 1) {
724 candidateHSVA[index] = x;
725 WebInspector.Color.hsva2rgba(candidateHSVA, candidateRGBA);
726 WebInspector.Color.blendColors(candidateRGBA, bgRGBA, blendedRGBA);
727 var fgLuminance = WebInspector.Color.luminance(blendedRGBA);
728 var dLuminance = fgLuminance - desiredLuminance;
729
730 if (Math.abs(dLuminance) < (onAxis ? epsilon / 10 : epsilon))
731 return x;
732 else
733 x += (index === V ? -dLuminance : dLuminance);
734 }
735 return null;
736 }
737
738 for (var s = 0; s < 1 + dS; s += dS) {
739 s = Math.min(1, s);
740 candidateHSVA[S] = s;
741
742 var v = lastV;
743 v = lastV + currentSlope * dS;
744
745 v = approach(V, v, s === 0);
746 if (v === null)
747 break;
748
749 currentSlope = (v - lastV) / dS;
750
751 pathBuilder.push(pathBuilder.length ? 'L' : 'M');
752 pathBuilder.push(s * width);
753 pathBuilder.push((1 - v) * height);
754 }
755
756 if (s < 1 + dS) {
757 s -= dS;
758 candidateHSVA[V] = 1;
759 s = approach(S, s, true);
760 if (s !== null)
761 pathBuilder = pathBuilder.concat(['L', s * width, -1]);
762 }
763
764 this._contrastRatioLine.setAttribute('d', pathBuilder.join(' '));
765 }
766
767 _updateUI() {
768 var h = WebInspector.Color.fromHSVA([this._hsv[0], 1, 1, 1]);
769 this._colorElement.style.backgroundColor = /** @type {string} */ (h.asString (WebInspector.Color.Format.RGB));
770 if (Runtime.experiments.isEnabled('colorContrastRatio')) {
771 // TODO(samli): Determine size of text and switch between AA/AAA ratings.
772 this._drawContrastRatioLine(4.5);
773 }
774 this._swatchInnerElement.style.backgroundColor =
775 /** @type {string} */ (this._color().asString(WebInspector.Color.Format. RGBA));
776 // Show border if the swatch is white.
777 this._swatchInnerElement.classList.toggle('swatch-inner-white', this._color( ).hsla()[2] > 0.9);
778 this._colorDragElement.style.backgroundColor =
779 /** @type {string} */ (this._color().asString(WebInspector.Color.Format. RGBA));
780 var noAlpha = WebInspector.Color.fromHSVA(this._hsv.slice(0, 3).concat(1));
781 this._alphaElementBackground.style.backgroundImage =
782 String.sprintf('linear-gradient(to right, rgba(0,0,0,0), %s)', noAlpha.a sString(WebInspector.Color.Format.RGB));
783 }
784
785 _formatViewSwitch() {
786 var cf = WebInspector.Color.Format;
787 var format = cf.RGB;
788 if (this._colorFormat === cf.RGB)
789 format = cf.HSL;
790 else if (this._colorFormat === cf.HSL && !this._color().hasAlpha())
791 format = this._originalFormat === cf.ShortHEX ? cf.ShortHEX : cf.HEX;
792 this._innerSetColor(undefined, '', format, WebInspector.Spectrum._ChangeSour ce.Other);
793 }
794
795 /**
796 * @param {!Event} event
797 */
798 _inputChanged(event) {
799 /**
800 * @param {!Element} element
801 * @return {string}
802 */
803 function elementValue(element) {
804 return element.value;
805 }
806
807 var inputElement = /** @type {!Element} */ (event.currentTarget);
808 var newValue = WebInspector.createReplacementString(inputElement.value, even t);
809 if (newValue) {
810 inputElement.value = newValue;
811 inputElement.selectionStart = 0;
812 inputElement.selectionEnd = newValue.length;
813 event.consume(true);
814 }
815
816 const cf = WebInspector.Color.Format;
817 var colorString;
818 if (this._colorFormat === cf.HEX || this._colorFormat === cf.ShortHEX) {
819 colorString = this._hexValue.value;
820 } else {
821 var format = this._colorFormat === cf.RGB ? 'rgba' : 'hsla';
822 var values = this._textValues.map(elementValue).join(', ');
823 colorString = String.sprintf('%s(%s)', format, values);
824 }
825
826 var color = WebInspector.Color.parse(colorString);
827 if (!color)
828 return;
829 var hsv = color.hsva();
830 if (this._colorFormat === cf.HEX || this._colorFormat === cf.ShortHEX)
831 this._colorFormat = color.canBeShortHex() ? cf.ShortHEX : cf.HEX;
832 this._innerSetColor(hsv, colorString, undefined, WebInspector.Spectrum._Chan geSource.Input);
833 }
834
835 /**
836 * @override
837 */
838 wasShown() {
839 this._hueAlphaWidth = this._hueElement.offsetWidth;
840 this.slideHelperWidth = this._hueSlider.offsetWidth / 2;
841 this.dragWidth = this._colorElement.offsetWidth;
842 this.dragHeight = this._colorElement.offsetHeight;
843 this._colorDragElementHeight = this._colorDragElement.offsetHeight / 2;
844 this._innerSetColor(undefined, undefined, undefined, WebInspector.Spectrum._ ChangeSource.Model);
845 this._toggleColorPicker(true);
846 WebInspector.targetManager.addModelListener(
847 WebInspector.ResourceTreeModel, WebInspector.ResourceTreeModel.Events.Co lorPicked, this._colorPicked, this);
848 }
849
850 /**
851 * @override
852 */
853 willHide() {
854 this._toggleColorPicker(false);
855 WebInspector.targetManager.removeModelListener(
856 WebInspector.ResourceTreeModel, WebInspector.ResourceTreeModel.Events.Co lorPicked, this._colorPicked, this);
857 }
858
859 /**
860 * @param {boolean=} enabled
861 * @param {!WebInspector.Event=} event
862 */
863 _toggleColorPicker(enabled, event) {
864 if (enabled === undefined)
865 enabled = !this._colorPickerButton.toggled();
866 this._colorPickerButton.setToggled(enabled);
867 for (var target of WebInspector.targetManager.targets())
868 target.pageAgent().setColorPickerEnabled(enabled);
869 }
870
871 /**
872 * @param {!WebInspector.Event} event
873 */
874 _colorPicked(event) {
875 var rgbColor = /** @type {!DOMAgent.RGBA} */ (event.data);
876 var rgba = [rgbColor.r, rgbColor.g, rgbColor.b, (rgbColor.a / 2.55 | 0) / 10 0];
877 var color = WebInspector.Color.fromRGBA(rgba);
878 this._innerSetColor(color.hsva(), '', undefined, WebInspector.Spectrum._Chan geSource.Other);
879 InspectorFrontendHost.bringToFront();
880 }
185 }; 881 };
186 882
187 WebInspector.Spectrum._ChangeSource = { 883 WebInspector.Spectrum._ChangeSource = {
188 Input: "Input", 884 Input: 'Input',
189 Model: "Model", 885 Model: 'Model',
190 Other: "Other" 886 Other: 'Other'
191 }; 887 };
192 888
193 /** @enum {symbol} */ 889 /** @enum {symbol} */
194 WebInspector.Spectrum.Events = { 890 WebInspector.Spectrum.Events = {
195 ColorChanged: Symbol("ColorChanged"), 891 ColorChanged: Symbol('ColorChanged'),
196 SizeChanged: Symbol("SizeChanged") 892 SizeChanged: Symbol('SizeChanged')
197 }; 893 };
198 894
199 WebInspector.Spectrum._colorChipSize = 24; 895 WebInspector.Spectrum._colorChipSize = 24;
200 WebInspector.Spectrum._itemsPerPaletteRow = 8; 896 WebInspector.Spectrum._itemsPerPaletteRow = 8;
201 897
202 WebInspector.Spectrum.prototype = {
203 _updatePalettePanel: function()
204 {
205 this._palettePanel.removeChildren();
206 var title = this._palettePanel.createChild("div", "palette-title");
207 title.textContent = WebInspector.UIString("Color Palettes");
208 var toolbar = new WebInspector.Toolbar("", this._palettePanel);
209 var closeButton = new WebInspector.ToolbarButton("Return to color picker ", "delete-toolbar-item");
210 closeButton.addEventListener("click", this._togglePalettePanel.bind(this , false));
211 toolbar.appendToolbarItem(closeButton);
212 for (var palette of this._palettes.values())
213 this._palettePanel.appendChild(this._createPreviewPaletteElement(pal ette));
214 },
215
216 /**
217 * @param {boolean} show
218 */
219 _togglePalettePanel: function(show)
220 {
221 if (this._palettePanelShowing === show)
222 return;
223 if (show)
224 this._updatePalettePanel();
225 this._focus();
226 this._palettePanelShowing = show;
227 this.contentElement.classList.toggle("palette-panel-showing", show);
228 },
229
230 _focus: function()
231 {
232 if (this.isShowing())
233 this.contentElement.focus();
234 },
235
236 /**
237 * @param {string} colorText
238 * @param {number=} animationDelay
239 * @return {!Element}
240 */
241 _createPaletteColor: function(colorText, animationDelay)
242 {
243 var element = createElementWithClass("div", "spectrum-palette-color");
244 element.style.background = String.sprintf("linear-gradient(%s, %s), url( Images/checker.png)", colorText, colorText);
245 if (animationDelay)
246 element.animate([{ opacity: 0 }, { opacity: 1 }], { duration: 100, d elay: animationDelay, fill: "backwards" });
247 element.title = colorText;
248 return element;
249 },
250
251 /**
252 * @param {!WebInspector.Spectrum.Palette} palette
253 * @param {boolean} animate
254 * @param {!Event=} event
255 */
256 _showPalette: function(palette, animate, event)
257 {
258 this._resizeForSelectedPalette();
259 this._paletteContainer.removeChildren();
260 for (var i = 0; i < palette.colors.length; i++) {
261 var animationDelay = animate ? i * 100 / palette.colors.length : 0;
262 var colorElement = this._createPaletteColor(palette.colors[i], anima tionDelay);
263 colorElement.addEventListener("mousedown", this._paletteColorSelecte d.bind(this, palette.colors[i], palette.matchUserFormat));
264 if (palette.mutable) {
265 colorElement.__mutable = true;
266 colorElement.__color = palette.colors[i];
267 colorElement.addEventListener("contextmenu", this._showPaletteCo lorContextMenu.bind(this, i));
268 } else if (palette === WebInspector.Spectrum.MaterialPalette) {
269 colorElement.classList.add("has-material-shades");
270 var shadow = colorElement.createChild("div", "spectrum-palette-c olor spectrum-palette-color-shadow");
271 shadow.style.background = palette.colors[i];
272 shadow = colorElement.createChild("div", "spectrum-palette-color spectrum-palette-color-shadow");
273 shadow.style.background = palette.colors[i];
274 colorElement.title = WebInspector.UIString(palette.colors[i] + " . Long-click to show alternate shades.");
275 new WebInspector.LongClickController(colorElement, this._showLig htnessShades.bind(this, colorElement, palette.colors[i]));
276 }
277 this._paletteContainer.appendChild(colorElement);
278 }
279 this._paletteContainerMutable = palette.mutable;
280
281 var numItems = palette.colors.length;
282 if (palette.mutable)
283 numItems++;
284 if (palette.mutable) {
285 this._paletteContainer.appendChild(this._addColorToolbar.element);
286 this._paletteContainer.appendChild(this._deleteIconToolbar.element);
287 } else {
288 this._addColorToolbar.element.remove();
289 this._deleteIconToolbar.element.remove();
290 }
291
292 this._togglePalettePanel(false);
293 this._focus();
294 },
295
296 /**
297 * @param {!Element} colorElement
298 * @param {string} colorText
299 * @param {!Event} event
300 */
301 _showLightnessShades: function(colorElement, colorText, event)
302 {
303 /**
304 * @param {!Element} element
305 * @this {!WebInspector.Spectrum}
306 */
307 function closeLightnessShades(element)
308 {
309 this._shadesContainer.classList.add("hidden");
310 element.classList.remove("spectrum-shades-shown");
311 this._shadesContainer.ownerDocument.removeEventListener("mousedown", this._shadesCloseHandler, true);
312 delete this._shadesCloseHandler;
313 }
314
315 if (this._shadesCloseHandler)
316 this._shadesCloseHandler();
317
318 this._shadesContainer.classList.remove("hidden");
319 this._shadesContainer.removeChildren();
320 this._shadesContainer.animate([{ transform: "scaleY(0)", opacity: "0" }, { transform: "scaleY(1)", opacity: "1" }], { duration: 200, easing: "cubic-bezi er(0.4, 0, 0.2, 1)" });
321 this._shadesContainer.style.top = colorElement.offsetTop + colorElement. parentElement.offsetTop + "px";
322 this._shadesContainer.style.left = colorElement.offsetLeft + "px";
323 colorElement.classList.add("spectrum-shades-shown");
324
325 var shades = WebInspector.Spectrum.MaterialPaletteShades[colorText];
326 for (var i = shades.length - 1; i >= 0; i--) {
327 var shadeElement = this._createPaletteColor(shades[i], i * 200 / sha des.length + 100);
328 shadeElement.addEventListener("mousedown", this._paletteColorSelecte d.bind(this, shades[i], false));
329 this._shadesContainer.appendChild(shadeElement);
330 }
331
332 this._shadesContainer.focus();
333 this._shadesCloseHandler = closeLightnessShades.bind(this, colorElement) ;
334 this._shadesContainer.ownerDocument.addEventListener("mousedown", this._ shadesCloseHandler, true);
335 },
336
337 /**
338 * @param {!Event} e
339 * @return {number}
340 */
341 _slotIndexForEvent: function(e)
342 {
343 var localX = e.pageX - this._paletteContainer.totalOffsetLeft();
344 var localY = e.pageY - this._paletteContainer.totalOffsetTop();
345 var col = Math.min(localX / WebInspector.Spectrum._colorChipSize | 0, We bInspector.Spectrum._itemsPerPaletteRow - 1);
346 var row = (localY / WebInspector.Spectrum._colorChipSize) | 0;
347 return Math.min(row * WebInspector.Spectrum._itemsPerPaletteRow + col, t his._customPaletteSetting.get().colors.length - 1);
348 },
349
350 /**
351 * @param {!Event} e
352 * @return {boolean}
353 */
354 _isDraggingToBin: function(e)
355 {
356 return e.pageX > this._deleteIconToolbar.element.totalOffsetLeft();
357 },
358
359 /**
360 * @param {!Event} e
361 * @return {boolean}
362 */
363 _paletteDragStart: function(e)
364 {
365 var element = e.deepElementFromPoint();
366 if (!element || !element.__mutable)
367 return false;
368
369 var index = this._slotIndexForEvent(e);
370 this._dragElement = element;
371 this._dragHotSpotX = e.pageX - (index % WebInspector.Spectrum._itemsPerP aletteRow) * WebInspector.Spectrum._colorChipSize;
372 this._dragHotSpotY = e.pageY - (index / WebInspector.Spectrum._itemsPerP aletteRow | 0) * WebInspector.Spectrum._colorChipSize;
373 return true;
374 },
375
376 /**
377 * @param {!Event} e
378 */
379 _paletteDrag: function(e)
380 {
381 if (e.pageX < this._paletteContainer.totalOffsetLeft() || e.pageY < this ._paletteContainer.totalOffsetTop())
382 return;
383 var newIndex = this._slotIndexForEvent(e);
384 var offsetX = e.pageX - (newIndex % WebInspector.Spectrum._itemsPerPalet teRow) * WebInspector.Spectrum._colorChipSize;
385 var offsetY = e.pageY - (newIndex / WebInspector.Spectrum._itemsPerPalet teRow | 0) * WebInspector.Spectrum._colorChipSize;
386
387 var isDeleting = this._isDraggingToBin(e);
388 this._deleteIconToolbar.element.classList.add("dragging");
389 this._deleteIconToolbar.element.classList.toggle("delete-color-toolbar-a ctive", isDeleting);
390 var dragElementTransform = "translateX(" + (offsetX - this._dragHotSpotX ) + "px) translateY(" + (offsetY - this._dragHotSpotY) + "px)";
391 this._dragElement.style.transform = isDeleting ? dragElementTransform + " scale(0.8)" : dragElementTransform;
392 var children = Array.prototype.slice.call(this._paletteContainer.childre n);
393 var index = children.indexOf(this._dragElement);
394 /** @type {!Map.<!Element, {left: number, top: number}>} */
395 var swatchOffsets = new Map();
396 for (var swatch of children)
397 swatchOffsets.set(swatch, swatch.totalOffset());
398
399 if (index !== newIndex)
400 this._paletteContainer.insertBefore(this._dragElement, children[newI ndex > index ? newIndex + 1 : newIndex]);
401
402 for (var swatch of children) {
403 if (swatch === this._dragElement)
404 continue;
405 var before = swatchOffsets.get(swatch);
406 var after = swatch.totalOffset();
407 if (before.left !== after.left || before.top !== after.top) {
408 swatch.animate([
409 { transform: "translateX(" + (before.left - after.left) + "p x) translateY(" + (before.top - after.top) + "px)" },
410 { transform: "none" }], { duration: 100, easing: "cubic-bezi er(0, 0, 0.2, 1)" });
411 }
412 }
413 },
414
415 /**
416 * @param {!Event} e
417 */
418 _paletteDragEnd: function(e)
419 {
420 if (this._isDraggingToBin(e))
421 this._dragElement.remove();
422 this._dragElement.style.removeProperty("transform");
423 var children = this._paletteContainer.children;
424 var colors = [];
425 for (var i = 0; i < children.length; ++i) {
426 if (children[i].__color)
427 colors.push(children[i].__color);
428 }
429 var palette = this._customPaletteSetting.get();
430 palette.colors = colors;
431 this._customPaletteSetting.set(palette);
432 this._showPalette(this._customPaletteSetting.get(), false);
433
434 this._deleteIconToolbar.element.classList.remove("dragging");
435 this._deleteIconToolbar.element.classList.remove("delete-color-toolbar-a ctive");
436 },
437
438 _loadPalettes: function()
439 {
440 this._palettes.set(WebInspector.Spectrum.MaterialPalette.title, WebInspe ctor.Spectrum.MaterialPalette);
441 /** @type {!WebInspector.Spectrum.Palette} */
442 var defaultCustomPalette = { title: "Custom", colors: [], mutable: true };
443 this._customPaletteSetting = WebInspector.settings.createSetting("custom ColorPalette", defaultCustomPalette);
444 this._palettes.set(this._customPaletteSetting.get().title, this._customP aletteSetting.get());
445
446 this._selectedColorPalette = WebInspector.settings.createSetting("select edColorPalette", WebInspector.Spectrum.GeneratedPaletteTitle);
447 var palette = this._palettes.get(this._selectedColorPalette.get());
448 if (palette)
449 this._showPalette(palette, true);
450 },
451
452 /**
453 * @param {!WebInspector.Spectrum.Palette} generatedPalette
454 */
455 _generatedPaletteLoaded: function(generatedPalette)
456 {
457 if (generatedPalette.colors.length)
458 this._palettes.set(generatedPalette.title, generatedPalette);
459 if (this._selectedColorPalette.get() !== generatedPalette.title) {
460 return;
461 } else if (!generatedPalette.colors.length) {
462 this._paletteSelected(WebInspector.Spectrum.MaterialPalette);
463 return;
464 }
465 this._showPalette(generatedPalette, true);
466 },
467
468 /**
469 * @param {!WebInspector.Spectrum.Palette} palette
470 * @return {!Element}
471 */
472 _createPreviewPaletteElement: function(palette)
473 {
474 var colorsPerPreviewRow = 5;
475 var previewElement = createElementWithClass("div", "palette-preview");
476 var titleElement = previewElement.createChild("div", "palette-preview-ti tle");
477 titleElement.textContent = palette.title;
478 for (var i = 0; i < colorsPerPreviewRow && i < palette.colors.length; i+ +)
479 previewElement.appendChild(this._createPaletteColor(palette.colors[i ]));
480 for (; i < colorsPerPreviewRow; i++)
481 previewElement.createChild("div", "spectrum-palette-color empty-colo r");
482 previewElement.addEventListener("click", this._paletteSelected.bind(this , palette));
483 return previewElement;
484 },
485
486 /**
487 * @param {!WebInspector.Spectrum.Palette} palette
488 */
489 _paletteSelected: function(palette)
490 {
491 this._selectedColorPalette.set(palette.title);
492 this._showPalette(palette, true);
493 },
494
495 _resizeForSelectedPalette: function()
496 {
497 var palette = this._palettes.get(this._selectedColorPalette.get());
498 if (!palette)
499 return;
500 var numColors = palette.colors.length;
501 if (palette === this._customPaletteSetting.get())
502 numColors++;
503 var rowsNeeded = Math.max(1, Math.ceil(numColors / WebInspector.Spectrum ._itemsPerPaletteRow));
504 if (this._numPaletteRowsShown === rowsNeeded)
505 return;
506 this._numPaletteRowsShown = rowsNeeded;
507 var paletteColorHeight = 12;
508 var paletteMargin = 12;
509 var paletteTop = 235;
510 this.element.style.height = (paletteTop + paletteMargin + (paletteColorH eight + paletteMargin) * rowsNeeded) + "px";
511 this.dispatchEventToListeners(WebInspector.Spectrum.Events.SizeChanged);
512 },
513
514 /**
515 * @param {string} colorText
516 * @param {boolean} matchUserFormat
517 */
518 _paletteColorSelected: function(colorText, matchUserFormat)
519 {
520 var color = WebInspector.Color.parse(colorText);
521 if (!color)
522 return;
523 this._innerSetColor(color.hsva(), colorText, matchUserFormat ? this._col orFormat : color.format(), WebInspector.Spectrum._ChangeSource.Other);
524 },
525
526 _addColorToCustomPalette: function()
527 {
528 var palette = this._customPaletteSetting.get();
529 palette.colors.push(this.colorString());
530 this._customPaletteSetting.set(palette);
531 this._showPalette(this._customPaletteSetting.get(), false);
532 },
533
534 /**
535 * @param {number} colorIndex
536 * @param {!Event} event
537 */
538 _showPaletteColorContextMenu: function(colorIndex, event)
539 {
540 if (!this._paletteContainerMutable)
541 return;
542 var contextMenu = new WebInspector.ContextMenu(event);
543 if (colorIndex !== -1) {
544 contextMenu.appendItem(WebInspector.UIString("Remove color"), this._ deletePaletteColors.bind(this, colorIndex, false));
545 contextMenu.appendItem(WebInspector.UIString("Remove all to the righ t"), this._deletePaletteColors.bind(this, colorIndex, true));
546 }
547 contextMenu.appendItem(WebInspector.UIString("Clear palette"), this._del etePaletteColors.bind(this, -1, true));
548 contextMenu.show();
549 },
550
551 /**
552 * @param {number} colorIndex
553 * @param {boolean} toRight
554 */
555 _deletePaletteColors: function(colorIndex, toRight)
556 {
557 var palette = this._customPaletteSetting.get();
558 if (toRight)
559 palette.colors.splice(colorIndex + 1, palette.colors.length - colorI ndex - 1);
560 else
561 palette.colors.splice(colorIndex, 1);
562 this._customPaletteSetting.set(palette);
563 this._showPalette(this._customPaletteSetting.get(), false);
564 },
565
566 /**
567 * @param {!WebInspector.Color} color
568 * @param {string} colorFormat
569 */
570 setColor: function(color, colorFormat)
571 {
572 this._originalFormat = colorFormat;
573 this._innerSetColor(color.hsva(), "", colorFormat, WebInspector.Spectrum ._ChangeSource.Model);
574 },
575
576 /**
577 * @param {!Array<number>|undefined} hsva
578 * @param {string|undefined} colorString
579 * @param {string|undefined} colorFormat
580 * @param {string} changeSource
581 */
582 _innerSetColor: function(hsva, colorString, colorFormat, changeSource)
583 {
584 if (hsva !== undefined)
585 this._hsv = hsva;
586 if (colorString !== undefined)
587 this._colorString = colorString;
588 if (colorFormat !== undefined) {
589 console.assert(colorFormat !== WebInspector.Color.Format.Original, " Spectrum's color format cannot be Original");
590 if (colorFormat === WebInspector.Color.Format.RGBA)
591 colorFormat = WebInspector.Color.Format.RGB;
592 else if (colorFormat === WebInspector.Color.Format.HSLA)
593 colorFormat = WebInspector.Color.Format.HSL;
594 this._colorFormat = colorFormat;
595 }
596
597 this._updateHelperLocations();
598 this._updateUI();
599
600 if (changeSource !== WebInspector.Spectrum._ChangeSource.Input)
601 this._updateInput();
602 if (changeSource !== WebInspector.Spectrum._ChangeSource.Model)
603 this.dispatchEventToListeners(WebInspector.Spectrum.Events.ColorChan ged, this.colorString());
604 },
605
606 /**
607 * @param {!WebInspector.Color} color
608 */
609 setContrastColor: function(color)
610 {
611 this._contrastColor = color;
612 this._updateUI();
613 },
614
615 /**
616 * @return {!WebInspector.Color}
617 */
618 _color: function()
619 {
620 return WebInspector.Color.fromHSVA(this._hsv);
621 },
622
623 /**
624 * @return {string}
625 */
626 colorString: function()
627 {
628 if (this._colorString)
629 return this._colorString;
630 var cf = WebInspector.Color.Format;
631 var color = this._color();
632 var colorString = color.asString(this._colorFormat);
633 if (colorString)
634 return colorString;
635
636 if (this._colorFormat === cf.Nickname || this._colorFormat === cf.ShortH EX) {
637 colorString = color.asString(cf.HEX);
638 if (colorString)
639 return colorString;
640 }
641
642 console.assert(color.hasAlpha());
643 return this._colorFormat === cf.HSL ? /** @type {string} */(color.asStri ng(cf.HSLA)) : /** @type {string} */(color.asString(cf.RGBA));
644 },
645
646 _updateHelperLocations: function()
647 {
648 var h = this._hsv[0];
649 var s = this._hsv[1];
650 var v = this._hsv[2];
651 var alpha = this._hsv[3];
652
653 // Where to show the little circle that displays your current selected c olor.
654 var dragX = s * this.dragWidth;
655 var dragY = this.dragHeight - (v * this.dragHeight);
656
657 dragX = Math.max(-this._colorDragElementHeight,
658 Math.min(this.dragWidth - this._colorDragElementHeight, dragX - this._colorDragElementHeight));
659 dragY = Math.max(-this._colorDragElementHeight,
660 Math.min(this.dragHeight - this._colorDragElementHeight, dragY - this._colorDragElementHeight));
661
662 this._colorDragElement.positionAt(dragX, dragY);
663
664 // Where to show the bar that displays your current selected hue.
665 var hueSlideX = (1 - h) * this._hueAlphaWidth - this.slideHelperWidth;
666 this._hueSlider.style.left = hueSlideX + "px";
667 var alphaSlideX = alpha * this._hueAlphaWidth - this.slideHelperWidth;
668 this._alphaSlider.style.left = alphaSlideX + "px";
669 },
670
671 _updateInput: function()
672 {
673 var cf = WebInspector.Color.Format;
674 if (this._colorFormat === cf.HEX || this._colorFormat === cf.ShortHEX || this._colorFormat === cf.Nickname) {
675 this._hexContainer.hidden = false;
676 this._displayContainer.hidden = true;
677 if (this._colorFormat === cf.ShortHEX && this._color().canBeShortHex ())
678 this._hexValue.value = this._color().asString(cf.ShortHEX);
679 else
680 this._hexValue.value = this._color().asString(cf.HEX);
681 } else {
682 // RGBA, HSLA display.
683 this._hexContainer.hidden = true;
684 this._displayContainer.hidden = false;
685 var isRgb = this._colorFormat === cf.RGB;
686 this._textLabels.textContent = isRgb ? "RGBA" : "HSLA";
687 var colorValues = isRgb ? this._color().canonicalRGBA() : this._colo r().canonicalHSLA();
688 for (var i = 0; i < 3; ++i) {
689 this._textValues[i].value = colorValues[i];
690 if (!isRgb && (i === 1 || i === 2))
691 this._textValues[i].value += "%";
692 }
693 this._textValues[3].value = Math.round(colorValues[3] * 100) / 100;
694 }
695 },
696
697 /**
698 * @param {number} requiredContrast
699 */
700 _drawContrastRatioLine: function(requiredContrast)
701 {
702 if (!this._contrastColor || !this.dragWidth || !this.dragHeight)
703 return;
704
705 /** const */ var width = this.dragWidth;
706 /** const */ var height = this.dragHeight;
707 /** const */ var dS = 0.02;
708 /** const */ var epsilon = 0.002;
709 /** const */ var H = 0;
710 /** const */ var S = 1;
711 /** const */ var V = 2;
712 /** const */ var A = 3;
713
714 var fgRGBA = [];
715 WebInspector.Color.hsva2rgba(this._hsv, fgRGBA);
716 var fgLuminance = WebInspector.Color.luminance(fgRGBA);
717 var bgRGBA = this._contrastColor.rgba();
718 var bgLuminance = WebInspector.Color.luminance(bgRGBA);
719 var fgIsLighter = fgLuminance > bgLuminance;
720 var desiredLuminance = WebInspector.Color.desiredLuminance(bgLuminance, requiredContrast, fgIsLighter);
721
722 var lastV = this._hsv[V];
723 var currentSlope = 0;
724 var candidateHSVA = [this._hsv[H], 0, 0, this._hsv[A]];
725 var pathBuilder = [];
726 var candidateRGBA = [];
727 WebInspector.Color.hsva2rgba(candidateHSVA, candidateRGBA);
728 var blendedRGBA = [];
729 WebInspector.Color.blendColors(candidateRGBA, bgRGBA, blendedRGBA);
730
731 /**
732 * Approach the desired contrast ratio by modifying the given component
733 * from the given starting value.
734 * @param {number} index
735 * @param {number} x
736 * @param {boolean} onAxis
737 * @return {?number}
738 */
739 function approach(index, x, onAxis)
740 {
741 while (0 <= x && x <= 1) {
742 candidateHSVA[index] = x;
743 WebInspector.Color.hsva2rgba(candidateHSVA, candidateRGBA);
744 WebInspector.Color.blendColors(candidateRGBA, bgRGBA, blendedRGB A);
745 var fgLuminance = WebInspector.Color.luminance(blendedRGBA);
746 var dLuminance = fgLuminance - desiredLuminance;
747
748 if (Math.abs(dLuminance) < (onAxis ? epsilon / 10 : epsilon))
749 return x;
750 else
751 x += (index === V ? -dLuminance : dLuminance);
752 }
753 return null;
754 }
755
756 for (var s = 0; s < 1 + dS; s += dS) {
757 s = Math.min(1, s);
758 candidateHSVA[S] = s;
759
760 var v = lastV;
761 v = lastV + currentSlope * dS;
762
763 v = approach(V, v, s === 0);
764 if (v === null)
765 break;
766
767 currentSlope = (v - lastV) / dS;
768
769 pathBuilder.push(pathBuilder.length ? "L" : "M");
770 pathBuilder.push(s * width);
771 pathBuilder.push((1 - v) * height);
772 }
773
774 if (s < 1 + dS) {
775 s -= dS;
776 candidateHSVA[V] = 1;
777 s = approach(S, s, true);
778 if (s !== null)
779 pathBuilder = pathBuilder.concat(["L", s * width, -1]);
780 }
781
782 this._contrastRatioLine.setAttribute("d", pathBuilder.join(" "));
783 },
784
785 _updateUI: function()
786 {
787 var h = WebInspector.Color.fromHSVA([this._hsv[0], 1, 1, 1]);
788 this._colorElement.style.backgroundColor = /** @type {string} */ (h.asSt ring(WebInspector.Color.Format.RGB));
789 if (Runtime.experiments.isEnabled("colorContrastRatio")) {
790 // TODO(samli): Determine size of text and switch between AA/AAA rat ings.
791 this._drawContrastRatioLine(4.5);
792 }
793 this._swatchInnerElement.style.backgroundColor = /** @type {string} */ ( this._color().asString(WebInspector.Color.Format.RGBA));
794 // Show border if the swatch is white.
795 this._swatchInnerElement.classList.toggle("swatch-inner-white", this._co lor().hsla()[2] > 0.9);
796 this._colorDragElement.style.backgroundColor = /** @type {string} */ (th is._color().asString(WebInspector.Color.Format.RGBA));
797 var noAlpha = WebInspector.Color.fromHSVA(this._hsv.slice(0,3).concat(1) );
798 this._alphaElementBackground.style.backgroundImage = String.sprintf("lin ear-gradient(to right, rgba(0,0,0,0), %s)", noAlpha.asString(WebInspector.Color. Format.RGB));
799 },
800
801 _formatViewSwitch: function()
802 {
803 var cf = WebInspector.Color.Format;
804 var format = cf.RGB;
805 if (this._colorFormat === cf.RGB)
806 format = cf.HSL;
807 else if (this._colorFormat === cf.HSL && !this._color().hasAlpha())
808 format = this._originalFormat === cf.ShortHEX ? cf.ShortHEX : cf.HEX ;
809 this._innerSetColor(undefined, "", format, WebInspector.Spectrum._Change Source.Other);
810 },
811
812 /**
813 * @param {!Event} event
814 */
815 _inputChanged: function(event)
816 {
817 /**
818 * @param {!Element} element
819 * @return {string}
820 */
821 function elementValue(element)
822 {
823 return element.value;
824 }
825
826 var inputElement = /** @type {!Element} */(event.currentTarget);
827 var newValue = WebInspector.createReplacementString(inputElement.value, event);
828 if (newValue) {
829 inputElement.value = newValue;
830 inputElement.selectionStart = 0;
831 inputElement.selectionEnd = newValue.length;
832 event.consume(true);
833 }
834
835 const cf = WebInspector.Color.Format;
836 var colorString;
837 if (this._colorFormat === cf.HEX || this._colorFormat === cf.ShortHEX) {
838 colorString = this._hexValue.value;
839 } else {
840 var format = this._colorFormat === cf.RGB ? "rgba" : "hsla";
841 var values = this._textValues.map(elementValue).join(", ");
842 colorString = String.sprintf("%s(%s)", format, values);
843 }
844
845 var color = WebInspector.Color.parse(colorString);
846 if (!color)
847 return;
848 var hsv = color.hsva();
849 if (this._colorFormat === cf.HEX || this._colorFormat === cf.ShortHEX)
850 this._colorFormat = color.canBeShortHex() ? cf.ShortHEX : cf.HEX;
851 this._innerSetColor(hsv, colorString, undefined, WebInspector.Spectrum._ ChangeSource.Input);
852 },
853
854 wasShown: function()
855 {
856 this._hueAlphaWidth = this._hueElement.offsetWidth;
857 this.slideHelperWidth = this._hueSlider.offsetWidth / 2;
858 this.dragWidth = this._colorElement.offsetWidth;
859 this.dragHeight = this._colorElement.offsetHeight;
860 this._colorDragElementHeight = this._colorDragElement.offsetHeight / 2;
861 this._innerSetColor(undefined, undefined, undefined, WebInspector.Spectr um._ChangeSource.Model);
862 this._toggleColorPicker(true);
863 WebInspector.targetManager.addModelListener(WebInspector.ResourceTreeMod el, WebInspector.ResourceTreeModel.Events.ColorPicked, this._colorPicked, this);
864 },
865
866 willHide: function()
867 {
868 this._toggleColorPicker(false);
869 WebInspector.targetManager.removeModelListener(WebInspector.ResourceTree Model, WebInspector.ResourceTreeModel.Events.ColorPicked, this._colorPicked, thi s);
870 },
871
872 /**
873 * @param {boolean=} enabled
874 * @param {!WebInspector.Event=} event
875 */
876 _toggleColorPicker: function(enabled, event)
877 {
878 if (enabled === undefined)
879 enabled = !this._colorPickerButton.toggled();
880 this._colorPickerButton.setToggled(enabled);
881 for (var target of WebInspector.targetManager.targets())
882 target.pageAgent().setColorPickerEnabled(enabled);
883 },
884
885 /**
886 * @param {!WebInspector.Event} event
887 */
888 _colorPicked: function(event)
889 {
890 var rgbColor = /** @type {!DOMAgent.RGBA} */ (event.data);
891 var rgba = [rgbColor.r, rgbColor.g, rgbColor.b, (rgbColor.a / 2.55 | 0) / 100];
892 var color = WebInspector.Color.fromRGBA(rgba);
893 this._innerSetColor(color.hsva(), "", undefined, WebInspector.Spectrum._ ChangeSource.Other);
894 InspectorFrontendHost.bringToFront();
895 },
896
897
898 __proto__: WebInspector.VBox.prototype
899 };
900
901 /** @typedef {{ title: string, colors: !Array.<string>, mutable: boolean }} */ 898 /** @typedef {{ title: string, colors: !Array.<string>, mutable: boolean }} */
902 WebInspector.Spectrum.Palette; 899 WebInspector.Spectrum.Palette;
903 WebInspector.Spectrum.GeneratedPaletteTitle = "Page colors"; 900 WebInspector.Spectrum.GeneratedPaletteTitle = 'Page colors';
904 901
905 /** 902 /**
906 * @constructor 903 * @unrestricted
907 * @param {function(!WebInspector.Spectrum.Palette)} callback
908 */ 904 */
909 WebInspector.Spectrum.PaletteGenerator = function(callback) 905 WebInspector.Spectrum.PaletteGenerator = class {
910 { 906 /**
907 * @param {function(!WebInspector.Spectrum.Palette)} callback
908 */
909 constructor(callback) {
911 this._callback = callback; 910 this._callback = callback;
912 /** @type {!Map.<string, number>} */ 911 /** @type {!Map.<string, number>} */
913 this._frequencyMap = new Map(); 912 this._frequencyMap = new Map();
914 var stylesheetPromises = []; 913 var stylesheetPromises = [];
915 for (var target of WebInspector.targetManager.targets(WebInspector.Target.Ca pability.DOM)) { 914 for (var target of WebInspector.targetManager.targets(WebInspector.Target.Ca pability.DOM)) {
916 var cssModel = WebInspector.CSSModel.fromTarget(target); 915 var cssModel = WebInspector.CSSModel.fromTarget(target);
917 for (var stylesheet of cssModel.allStyleSheets()) 916 for (var stylesheet of cssModel.allStyleSheets())
918 stylesheetPromises.push(new Promise(this._processStylesheet.bind(thi s, stylesheet))); 917 stylesheetPromises.push(new Promise(this._processStylesheet.bind(this, s tylesheet)));
919 } 918 }
920 Promise.all(stylesheetPromises) 919 Promise.all(stylesheetPromises).catchException(null).then(this._finish.bind( this));
921 .catchException(null) 920 }
922 .then(this._finish.bind(this)); 921
923 }; 922 /**
924 923 * @param {string} a
925 WebInspector.Spectrum.PaletteGenerator.prototype = { 924 * @param {string} b
925 * @return {number}
926 */
927 _frequencyComparator(a, b) {
928 return this._frequencyMap.get(b) - this._frequencyMap.get(a);
929 }
930
931 _finish() {
926 /** 932 /**
927 * @param {string} a 933 * @param {string} a
928 * @param {string} b 934 * @param {string} b
929 * @return {number} 935 * @return {number}
930 */ 936 */
931 _frequencyComparator: function(a, b) 937 function hueComparator(a, b) {
932 { 938 var hsva = paletteColors.get(a).hsva();
933 return this._frequencyMap.get(b) - this._frequencyMap.get(a); 939 var hsvb = paletteColors.get(b).hsva();
934 }, 940
935 941 // First trim the shades of gray
936 _finish: function() 942 if (hsvb[1] < 0.12 && hsva[1] < 0.12)
937 { 943 return hsvb[2] * hsvb[3] - hsva[2] * hsva[3];
938 /** 944 if (hsvb[1] < 0.12)
939 * @param {string} a 945 return -1;
940 * @param {string} b 946 if (hsva[1] < 0.12)
941 * @return {number} 947 return 1;
942 */ 948
943 function hueComparator(a, b) 949 // Equal hue -> sort by sat
944 { 950 if (hsvb[0] === hsva[0])
945 var hsva = paletteColors.get(a).hsva(); 951 return hsvb[1] * hsvb[3] - hsva[1] * hsva[3];
946 var hsvb = paletteColors.get(b).hsva(); 952
947 953 return (hsvb[0] + 0.94) % 1 - (hsva[0] + 0.94) % 1;
948 // First trim the shades of gray 954 }
949 if (hsvb[1] < 0.12 && hsva[1] < 0.12) 955
950 return hsvb[2] * hsvb[3] - hsva[2] * hsva[3]; 956 var colors = this._frequencyMap.keysArray();
951 if (hsvb[1] < 0.12) 957 colors = colors.sort(this._frequencyComparator.bind(this));
952 return -1; 958 /** @type {!Map.<string, !WebInspector.Color>} */
953 if (hsva[1] < 0.12) 959 var paletteColors = new Map();
954 return 1; 960 var colorsPerRow = 24;
955 961 while (paletteColors.size < colorsPerRow && colors.length) {
956 // Equal hue -> sort by sat 962 var colorText = colors.shift();
957 if (hsvb[0] === hsva[0]) 963 var color = WebInspector.Color.parse(colorText);
958 return hsvb[1] * hsvb[3] - hsva[1] * hsva[3]; 964 if (!color || color.nickname() === 'white' || color.nickname() === 'black' )
959 965 continue;
960 return (hsvb[0] + 0.94) % 1 - (hsva[0] + 0.94) % 1; 966 paletteColors.set(colorText, color);
961 } 967 }
962 968
963 var colors = this._frequencyMap.keysArray(); 969 this._callback({
964 colors = colors.sort(this._frequencyComparator.bind(this)); 970 title: WebInspector.Spectrum.GeneratedPaletteTitle,
965 /** @type {!Map.<string, !WebInspector.Color>} */ 971 colors: paletteColors.keysArray().sort(hueComparator),
966 var paletteColors = new Map(); 972 mutable: false
967 var colorsPerRow = 24; 973 });
968 while (paletteColors.size < colorsPerRow && colors.length) { 974 }
969 var colorText = colors.shift(); 975
970 var color = WebInspector.Color.parse(colorText); 976 /**
971 if (!color || color.nickname() === "white" || color.nickname() === " black") 977 * @param {!WebInspector.CSSStyleSheetHeader} stylesheet
972 continue; 978 * @param {function(?)} resolve
973 paletteColors.set(colorText, color); 979 * @this {WebInspector.Spectrum.PaletteGenerator}
974 } 980 */
975 981 _processStylesheet(stylesheet, resolve) {
976 this._callback({ title: WebInspector.Spectrum.GeneratedPaletteTitle, col ors: paletteColors.keysArray().sort(hueComparator), mutable: false });
977 },
978
979 /** 982 /**
980 * @param {!WebInspector.CSSStyleSheetHeader} stylesheet 983 * @param {?string} text
981 * @param {function(?)} resolve
982 * @this {WebInspector.Spectrum.PaletteGenerator} 984 * @this {WebInspector.Spectrum.PaletteGenerator}
983 */ 985 */
984 _processStylesheet: function(stylesheet, resolve) 986 function parseContent(text) {
985 { 987 text = text.toLowerCase();
986 /** 988 var regexResult = text.match(/((?:rgb|hsl)a?\([^)]+\)|#[0-9a-f]{6}|#[0-9a- f]{3})/g) || [];
987 * @param {?string} text 989 for (var c of regexResult) {
988 * @this {WebInspector.Spectrum.PaletteGenerator} 990 var frequency = this._frequencyMap.get(c) || 0;
989 */ 991 this._frequencyMap.set(c, ++frequency);
990 function parseContent(text) 992 }
991 { 993 resolve(null);
992 text = text.toLowerCase(); 994 }
993 var regexResult = text.match(/((?:rgb|hsl)a?\([^)]+\)|#[0-9a-f]{6}|# [0-9a-f]{3})/g) || []; 995
994 for (var c of regexResult) { 996 stylesheet.requestContent().then(parseContent.bind(this));
995 var frequency = this._frequencyMap.get(c) || 0; 997 }
996 this._frequencyMap.set(c, ++frequency);
997 }
998 resolve(null);
999 }
1000
1001 stylesheet.requestContent().then(parseContent.bind(this));
1002 }
1003 }; 998 };
1004 999
1005 WebInspector.Spectrum.MaterialPaletteShades = { 1000 WebInspector.Spectrum.MaterialPaletteShades = {
1006 "#F44336": ["#FFEBEE", "#FFCDD2", "#EF9A9A", "#E57373", "#EF5350", "#F44336" , "#E53935", "#D32F2F", "#C62828", "#B71C1C"], 1001 '#F44336':
1007 "#E91E63": ["#FCE4EC", "#F8BBD0", "#F48FB1", "#F06292", "#EC407A", "#E91E63" , "#D81B60", "#C2185B", "#AD1457", "#880E4F"], 1002 ['#FFEBEE', '#FFCDD2', '#EF9A9A', '#E57373', '#EF5350', '#F44336', '#E5393 5', '#D32F2F', '#C62828', '#B71C1C'],
1008 "#9C27B0": ["#F3E5F5", "#E1BEE7", "#CE93D8", "#BA68C8", "#AB47BC", "#9C27B0" , "#8E24AA", "#7B1FA2", "#6A1B9A", "#4A148C"], 1003 '#E91E63':
1009 "#673AB7": ["#EDE7F6", "#D1C4E9", "#B39DDB", "#9575CD", "#7E57C2", "#673AB7" , "#5E35B1", "#512DA8", "#4527A0", "#311B92"], 1004 ['#FCE4EC', '#F8BBD0', '#F48FB1', '#F06292', '#EC407A', '#E91E63', '#D81B6 0', '#C2185B', '#AD1457', '#880E4F'],
1010 "#3F51B5": ["#E8EAF6", "#C5CAE9", "#9FA8DA", "#7986CB", "#5C6BC0", "#3F51B5" , "#3949AB", "#303F9F", "#283593", "#1A237E"], 1005 '#9C27B0':
1011 "#2196F3": ["#E3F2FD", "#BBDEFB", "#90CAF9", "#64B5F6", "#42A5F5", "#2196F3" , "#1E88E5", "#1976D2", "#1565C0", "#0D47A1"], 1006 ['#F3E5F5', '#E1BEE7', '#CE93D8', '#BA68C8', '#AB47BC', '#9C27B0', '#8E24A A', '#7B1FA2', '#6A1B9A', '#4A148C'],
1012 "#03A9F4": ["#E1F5FE", "#B3E5FC", "#81D4FA", "#4FC3F7", "#29B6F6", "#03A9F4" , "#039BE5", "#0288D1", "#0277BD", "#01579B"], 1007 '#673AB7':
1013 "#00BCD4": ["#E0F7FA", "#B2EBF2", "#80DEEA", "#4DD0E1", "#26C6DA", "#00BCD4" , "#00ACC1", "#0097A7", "#00838F", "#006064"], 1008 ['#EDE7F6', '#D1C4E9', '#B39DDB', '#9575CD', '#7E57C2', '#673AB7', '#5E35B 1', '#512DA8', '#4527A0', '#311B92'],
1014 "#009688": ["#E0F2F1", "#B2DFDB", "#80CBC4", "#4DB6AC", "#26A69A", "#009688" , "#00897B", "#00796B", "#00695C", "#004D40"], 1009 '#3F51B5':
1015 "#4CAF50": ["#E8F5E9", "#C8E6C9", "#A5D6A7", "#81C784", "#66BB6A", "#4CAF50" , "#43A047", "#388E3C", "#2E7D32", "#1B5E20"], 1010 ['#E8EAF6', '#C5CAE9', '#9FA8DA', '#7986CB', '#5C6BC0', '#3F51B5', '#3949A B', '#303F9F', '#283593', '#1A237E'],
1016 "#8BC34A": ["#F1F8E9", "#DCEDC8", "#C5E1A5", "#AED581", "#9CCC65", "#8BC34A" , "#7CB342", "#689F38", "#558B2F", "#33691E"], 1011 '#2196F3':
1017 "#CDDC39": ["#F9FBE7", "#F0F4C3", "#E6EE9C", "#DCE775", "#D4E157", "#CDDC39" , "#C0CA33", "#AFB42B", "#9E9D24", "#827717"], 1012 ['#E3F2FD', '#BBDEFB', '#90CAF9', '#64B5F6', '#42A5F5', '#2196F3', '#1E88E 5', '#1976D2', '#1565C0', '#0D47A1'],
1018 "#FFEB3B": ["#FFFDE7", "#FFF9C4", "#FFF59D", "#FFF176", "#FFEE58", "#FFEB3B" , "#FDD835", "#FBC02D", "#F9A825", "#F57F17"], 1013 '#03A9F4':
1019 "#FFC107": ["#FFF8E1", "#FFECB3", "#FFE082", "#FFD54F", "#FFCA28", "#FFC107" , "#FFB300", "#FFA000", "#FF8F00", "#FF6F00"], 1014 ['#E1F5FE', '#B3E5FC', '#81D4FA', '#4FC3F7', '#29B6F6', '#03A9F4', '#039BE 5', '#0288D1', '#0277BD', '#01579B'],
1020 "#FF9800": ["#FFF3E0", "#FFE0B2", "#FFCC80", "#FFB74D", "#FFA726", "#FF9800" , "#FB8C00", "#F57C00", "#EF6C00", "#E65100"], 1015 '#00BCD4':
1021 "#FF5722": ["#FBE9E7", "#FFCCBC", "#FFAB91", "#FF8A65", "#FF7043", "#FF5722" , "#F4511E", "#E64A19", "#D84315", "#BF360C"], 1016 ['#E0F7FA', '#B2EBF2', '#80DEEA', '#4DD0E1', '#26C6DA', '#00BCD4', '#00ACC 1', '#0097A7', '#00838F', '#006064'],
1022 "#795548": ["#EFEBE9", "#D7CCC8", "#BCAAA4", "#A1887F", "#8D6E63", "#795548" , "#6D4C41", "#5D4037", "#4E342E", "#3E2723"], 1017 '#009688':
1023 "#9E9E9E": ["#FAFAFA", "#F5F5F5", "#EEEEEE", "#E0E0E0", "#BDBDBD", "#9E9E9E" , "#757575", "#616161", "#424242", "#212121"], 1018 ['#E0F2F1', '#B2DFDB', '#80CBC4', '#4DB6AC', '#26A69A', '#009688', '#00897 B', '#00796B', '#00695C', '#004D40'],
1024 "#607D8B": ["#ECEFF1", "#CFD8DC", "#B0BEC5", "#90A4AE", "#78909C", "#607D8B" , "#546E7A", "#455A64", "#37474F", "#263238"] 1019 '#4CAF50':
1020 ['#E8F5E9', '#C8E6C9', '#A5D6A7', '#81C784', '#66BB6A', '#4CAF50', '#43A04 7', '#388E3C', '#2E7D32', '#1B5E20'],
1021 '#8BC34A':
1022 ['#F1F8E9', '#DCEDC8', '#C5E1A5', '#AED581', '#9CCC65', '#8BC34A', '#7CB34 2', '#689F38', '#558B2F', '#33691E'],
1023 '#CDDC39':
1024 ['#F9FBE7', '#F0F4C3', '#E6EE9C', '#DCE775', '#D4E157', '#CDDC39', '#C0CA3 3', '#AFB42B', '#9E9D24', '#827717'],
1025 '#FFEB3B':
1026 ['#FFFDE7', '#FFF9C4', '#FFF59D', '#FFF176', '#FFEE58', '#FFEB3B', '#FDD83 5', '#FBC02D', '#F9A825', '#F57F17'],
1027 '#FFC107':
1028 ['#FFF8E1', '#FFECB3', '#FFE082', '#FFD54F', '#FFCA28', '#FFC107', '#FFB30 0', '#FFA000', '#FF8F00', '#FF6F00'],
1029 '#FF9800':
1030 ['#FFF3E0', '#FFE0B2', '#FFCC80', '#FFB74D', '#FFA726', '#FF9800', '#FB8C0 0', '#F57C00', '#EF6C00', '#E65100'],
1031 '#FF5722':
1032 ['#FBE9E7', '#FFCCBC', '#FFAB91', '#FF8A65', '#FF7043', '#FF5722', '#F4511 E', '#E64A19', '#D84315', '#BF360C'],
1033 '#795548':
1034 ['#EFEBE9', '#D7CCC8', '#BCAAA4', '#A1887F', '#8D6E63', '#795548', '#6D4C4 1', '#5D4037', '#4E342E', '#3E2723'],
1035 '#9E9E9E':
1036 ['#FAFAFA', '#F5F5F5', '#EEEEEE', '#E0E0E0', '#BDBDBD', '#9E9E9E', '#75757 5', '#616161', '#424242', '#212121'],
1037 '#607D8B':
1038 ['#ECEFF1', '#CFD8DC', '#B0BEC5', '#90A4AE', '#78909C', '#607D8B', '#546E7 A', '#455A64', '#37474F', '#263238']
1025 }; 1039 };
1026 1040
1027 WebInspector.Spectrum.MaterialPalette = { title: "Material", mutable: false, mat chUserFormat: true, colors: Object.keys(WebInspector.Spectrum.MaterialPaletteSha des) }; 1041 WebInspector.Spectrum.MaterialPalette = {
1042 title: 'Material',
1043 mutable: false,
1044 matchUserFormat: true,
1045 colors: Object.keys(WebInspector.Spectrum.MaterialPaletteShades)
1046 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698