<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[210260] trunk/Source/WebInspectorUI</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/210260">210260</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2017-01-03 17:26:58 -0800 (Tue, 03 Jan 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>Web Inspector: color picker should feature an editable CSS value
https://bugs.webkit.org/show_bug.cgi?id=124356

Patch by Devin Rousso &lt;dcrousso+webkit@gmail.com&gt; on 2017-01-03
Reviewed by Brian Burg.

* UserInterface/Views/ColorPicker.css:
(.color-picker):
(.color-picker &gt; .color-inputs):
(.color-picker &gt; .color-inputs &gt; div):
(.color-picker &gt; .color-inputs &gt; div[hidden]):
(.color-picker &gt; .color-inputs input):

* UserInterface/Views/ColorPicker.js:
(WebInspector.ColorPicker.createColorInput):
(WebInspector.ColorPicker):
(WebInspector.ColorPicker.prototype.set color):
(WebInspector.ColorPicker.prototype.sliderValueDidChange):
(WebInspector.ColorPicker.prototype._updateColor):
(WebInspector.ColorPicker.prototype._showColorComponentInputs.updateColorInput):
(WebInspector.ColorPicker.prototype._showColorComponentInputs):
(WebInspector.ColorPicker.prototype._handleColorInputInput):
Add an input element (with a label for the component name and its units) for each component
as part of the current color format (e.g. R, G, B, A).  If any of these inputs are changed
then the color is also changed and the &quot;ColorChanged&quot; event is fired.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsColorPickercss">trunk/Source/WebInspectorUI/UserInterface/Views/ColorPicker.css</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsColorPickerjs">trunk/Source/WebInspectorUI/UserInterface/Views/ColorPicker.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (210259 => 210260)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog        2017-01-04 01:14:59 UTC (rev 210259)
+++ trunk/Source/WebInspectorUI/ChangeLog        2017-01-04 01:26:58 UTC (rev 210260)
</span><span class="lines">@@ -1,3 +1,30 @@
</span><ins>+2017-01-03  Devin Rousso  &lt;dcrousso+webkit@gmail.com&gt;
+
+        Web Inspector: color picker should feature an editable CSS value
+        https://bugs.webkit.org/show_bug.cgi?id=124356
+
+        Reviewed by Brian Burg.
+
+        * UserInterface/Views/ColorPicker.css:
+        (.color-picker):
+        (.color-picker &gt; .color-inputs):
+        (.color-picker &gt; .color-inputs &gt; div):
+        (.color-picker &gt; .color-inputs &gt; div[hidden]):
+        (.color-picker &gt; .color-inputs input):
+
+        * UserInterface/Views/ColorPicker.js:
+        (WebInspector.ColorPicker.createColorInput):
+        (WebInspector.ColorPicker):
+        (WebInspector.ColorPicker.prototype.set color):
+        (WebInspector.ColorPicker.prototype.sliderValueDidChange):
+        (WebInspector.ColorPicker.prototype._updateColor):
+        (WebInspector.ColorPicker.prototype._showColorComponentInputs.updateColorInput):
+        (WebInspector.ColorPicker.prototype._showColorComponentInputs):
+        (WebInspector.ColorPicker.prototype._handleColorInputInput):
+        Add an input element (with a label for the component name and its units) for each component
+        as part of the current color format (e.g. R, G, B, A).  If any of these inputs are changed
+        then the color is also changed and the &quot;ColorChanged&quot; event is fired.
+
</ins><span class="cx"> 2017-01-03  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: &quot;Invalid Characters&quot; setting does the opposite of the checkbox
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsColorPickercss"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ColorPicker.css (210259 => 210260)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/ColorPicker.css        2017-01-04 01:14:59 UTC (rev 210259)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ColorPicker.css        2017-01-04 01:26:58 UTC (rev 210260)
</span><span class="lines">@@ -26,7 +26,7 @@
</span><span class="cx"> .color-picker {
</span><span class="cx">     position: relative;
</span><span class="cx">     width: 256px;
</span><del>-    height: 210px;
</del><ins>+    height: 236px;
</ins><span class="cx">     padding: 5px;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -53,3 +53,27 @@
</span><span class="cx"> .color-picker &gt; .opacity {
</span><span class="cx">     left: 238px;
</span><span class="cx"> }
</span><ins>+
+.color-picker &gt; .color-inputs {
+    display: flex;
+    justify-content: space-between;
+    top: 212px;
+    right: 0;
+    left: 0;
+}
+
+.color-picker &gt; .color-inputs &gt; div {
+    display: flex;
+    align-items: center;
+    width: 100%;
+    margin: 0 4px;
+}
+
+.color-picker &gt; .color-inputs &gt; div[hidden] {
+    display: none;
+}
+
+.color-picker &gt; .color-inputs input {
+    width: 100%;
+    margin: 0 2px;
+}
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsColorPickerjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ColorPicker.js (210259 => 210260)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/ColorPicker.js        2017-01-04 01:14:59 UTC (rev 210259)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ColorPicker.js        2017-01-04 01:26:58 UTC (rev 210260)
</span><span class="lines">@@ -41,17 +41,49 @@
</span><span class="cx">         this._opacitySlider.delegate = this;
</span><span class="cx">         this._opacitySlider.element.classList.add(&quot;opacity&quot;);
</span><span class="cx"> 
</span><ins>+        let colorInputsContainerElement = document.createElement(&quot;div&quot;);
+        colorInputsContainerElement.classList.add(&quot;color-inputs&quot;);
+
+        function createColorInput(label, {min, max, step, units} = {min: 0, max: 1, step: 0.01}) {
+            let containerElement = colorInputsContainerElement.createChild(&quot;div&quot;);
+
+            containerElement.append(label);
+
+            let numberInputElement = containerElement.createChild(&quot;input&quot;);
+            numberInputElement.type = &quot;number&quot;;
+            numberInputElement.min = min;
+            numberInputElement.max = max;
+            numberInputElement.step = step;
+            numberInputElement.addEventListener(&quot;input&quot;, this._handleColorInputInput.bind(this));
+
+            if (units &amp;&amp; units.length)
+                containerElement.append(units);
+
+            return {containerElement, numberInputElement};
+        }
+
+        this._colorInputs = new Map([
+            [&quot;R&quot;, createColorInput.call(this, &quot;R&quot;, {max: 255, step: 1})],
+            [&quot;G&quot;, createColorInput.call(this, &quot;G&quot;, {max: 255, step: 1})],
+            [&quot;B&quot;, createColorInput.call(this, &quot;B&quot;, {max: 255, step: 1})],
+            [&quot;H&quot;, createColorInput.call(this, &quot;H&quot;, {max: 360, step: 1})],
+            [&quot;S&quot;, createColorInput.call(this, &quot;S&quot;, {units: &quot;%&quot;})],
+            [&quot;L&quot;, createColorInput.call(this, &quot;L&quot;, {units: &quot;%&quot;})],
+            [&quot;A&quot;, createColorInput.call(this, &quot;A&quot;)]
+        ]);
+
</ins><span class="cx">         this._element = document.createElement(&quot;div&quot;);
</span><del>-        this._element.className = &quot;color-picker&quot;;
</del><ins>+        this._element.classList.add(&quot;color-picker&quot;);
</ins><span class="cx"> 
</span><span class="cx">         this._element.appendChild(this._colorWheel.element);
</span><span class="cx">         this._element.appendChild(this._brightnessSlider.element);
</span><span class="cx">         this._element.appendChild(this._opacitySlider.element);
</span><ins>+        this._element.appendChild(colorInputsContainerElement);
</ins><span class="cx"> 
</span><span class="cx">         this._opacity = 0;
</span><span class="cx">         this._opacityPattern = &quot;url(Images/Checkers.svg)&quot;;
</span><span class="cx"> 
</span><del>-        this._color = &quot;white&quot;;
</del><ins>+        this._color = WebInspector.Color.fromString(&quot;white&quot;);
</ins><span class="cx"> 
</span><span class="cx">         this._dontUpdateColor = false;
</span><span class="cx">     }
</span><span class="lines">@@ -95,16 +127,21 @@
</span><span class="cx"> 
</span><span class="cx">     set color(color)
</span><span class="cx">     {
</span><ins>+        if (!color)
+            return;
+
</ins><span class="cx">         this._dontUpdateColor = true;
</span><span class="cx"> 
</span><del>-        this._colorFormat = color.format;
</del><ins>+        this._color = color;
</ins><span class="cx"> 
</span><del>-        this._colorWheel.tintedColor = color;
</del><ins>+        this._colorWheel.tintedColor = this._color;
</ins><span class="cx">         this._brightnessSlider.value = this._colorWheel.brightness;
</span><span class="cx"> 
</span><del>-        this._opacitySlider.value = color.alpha;
-        this._updateSliders(this._colorWheel.rawColor, color);
</del><ins>+        this._opacitySlider.value = this._color.alpha;
+        this._updateSliders(this._colorWheel.rawColor, this._color);
</ins><span class="cx"> 
</span><ins>+        this._showColorComponentInputs();
+
</ins><span class="cx">         this._dontUpdateColor = false;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -120,6 +157,8 @@
</span><span class="cx">             this.opacity = value;
</span><span class="cx">         else if (slider === this._brightnessSlider)
</span><span class="cx">             this.brightness = value;
</span><ins>+
+        this._updateColor();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Private
</span><span class="lines">@@ -129,15 +168,24 @@
</span><span class="cx">         if (this._dontUpdateColor)
</span><span class="cx">             return;
</span><span class="cx"> 
</span><del>-        var opacity = Math.round(this._opacity * 100) / 100;
</del><ins>+        let opacity = Math.round(this._opacity * 100) / 100;
</ins><span class="cx"> 
</span><del>-        var components;
-        if (this._colorFormat === WebInspector.Color.Format.HSL || this._colorFormat === WebInspector.Color.Format.HSLA)
</del><ins>+        let format = this._color.format;
+        let components = null;
+        if (format === WebInspector.Color.Format.HSL || format === WebInspector.Color.Format.HSLA) {
</ins><span class="cx">             components = this._colorWheel.tintedColor.hsl.concat(opacity);
</span><del>-        else
</del><ins>+            if (opacity !== 1)
+                format = WebInspector.Color.Format.HSLA;
+        } else {
</ins><span class="cx">             components = this._colorWheel.tintedColor.rgb.concat(opacity);
</span><ins>+            if (opacity !== 1 &amp;&amp; format === WebInspector.Color.Format.RGB)
+                format = WebInspector.Color.Format.RGBA;
+        }
</ins><span class="cx"> 
</span><del>-        this._color = new WebInspector.Color(this._colorFormat, components);
</del><ins>+        this._color = new WebInspector.Color(format, components);
+
+        this._showColorComponentInputs();
+
</ins><span class="cx">         this.dispatchEventToListeners(WebInspector.ColorPicker.Event.ColorChanged, {color: this._color});
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -150,6 +198,81 @@
</span><span class="cx">         this._opacitySlider.element.style.backgroundImage = &quot;linear-gradient(90deg, &quot; + transparent + &quot;, &quot; + opaque + &quot;), &quot; + this._opacityPattern;
</span><span class="cx">         this._brightnessSlider.element.style.backgroundImage = &quot;linear-gradient(90deg, black, &quot; + rawColor + &quot;)&quot;;
</span><span class="cx">     }
</span><ins>+
+    _showColorComponentInputs()
+    {
+        function updateColorInput(key, value) {
+            let {containerElement, numberInputElement} = this._colorInputs.get(key);
+            numberInputElement.value = value;
+            containerElement.hidden = false;
+        }
+
+        for (let {containerElement} of this._colorInputs.values())
+            containerElement.hidden = true;
+
+        switch (this._color.format) {
+        case WebInspector.Color.Format.RGB:
+        case WebInspector.Color.Format.RGBA:
+            var [r, g, b] = this._color.rgb;
+            updateColorInput.call(this, &quot;R&quot;, r);
+            updateColorInput.call(this, &quot;G&quot;, g);
+            updateColorInput.call(this, &quot;B&quot;, b);
+            break;
+
+        case WebInspector.Color.Format.HSL:
+        case WebInspector.Color.Format.HSLA:
+            var [h, s, l] = this._color.hsl;
+            updateColorInput.call(this, &quot;H&quot;, h);
+            updateColorInput.call(this, &quot;S&quot;, s);
+            updateColorInput.call(this, &quot;L&quot;, l);
+            break;
+
+        default:
+            return;
+        }
+
+        if (this._color.format === WebInspector.Color.Format.RGBA || this._color.format === WebInspector.Color.Format.HSLA)
+            updateColorInput.call(this, &quot;A&quot;, this._color.alpha);
+    }
+
+    _handleColorInputInput(event)
+    {
+        let r = this._colorInputs.get(&quot;R&quot;).numberInputElement.value;
+        let g = this._colorInputs.get(&quot;G&quot;).numberInputElement.value;
+        let b = this._colorInputs.get(&quot;B&quot;).numberInputElement.value;
+        let h = this._colorInputs.get(&quot;H&quot;).numberInputElement.value;
+        let s = this._colorInputs.get(&quot;S&quot;).numberInputElement.value;
+        let l = this._colorInputs.get(&quot;L&quot;).numberInputElement.value;
+        let a = this._colorInputs.get(&quot;A&quot;).numberInputElement.value;
+
+        let colorString = &quot;&quot;;
+
+        switch (this._color.format) {
+        case WebInspector.Color.Format.RGB:
+            colorString = `rgb(${r}, ${g}, ${b})`;
+            break;
+
+        case WebInspector.Color.Format.RGBA:
+            colorString = `rgba(${r}, ${g}, ${b}, ${a})`;
+            break;
+
+        case WebInspector.Color.Format.HSL:
+            colorString = `hsl(${h}, ${s}%, ${l}%)`;
+            break;
+
+        case WebInspector.Color.Format.HSLA:
+            colorString = `hsla(${h}, ${s}%, ${l}%, ${a})`;
+            break;
+
+        default:
+            WebInspector.reportInternalError(`Input event fired for invalid color format &quot;${this._color.format}&quot;`);
+            return;
+        }
+
+        this.color = WebInspector.Color.fromString(colorString);
+
+        this.dispatchEventToListeners(WebInspector.ColorPicker.Event.ColorChanged, {color: this._color});
+    }
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> WebInspector.ColorPicker.Event = {
</span></span></pre>
</div>
</div>

</body>
</html>