Changeset 211057 in webkit


Ignore:
Timestamp:
Jan 23, 2017 1:27:26 PM (7 years ago)
Author:
commit-queue@webkit.org
Message:

Web Inspector: color picker should feature an editable CSS value
https://bugs.webkit.org/show_bug.cgi?id=124356

Patch by Devin Rousso <Devin Rousso> on 2017-01-23
Reviewed by Timothy Hatcher.

  • UserInterface/Views/ColorPicker.css:

(.color-picker):
(.color-picker.hide-inputs):
(.color-picker > .color-inputs):
(.color-picker > .color-inputs > div):
(.color-picker > .color-inputs > div[hidden]):
(.color-picker > .color-inputs input):

  • UserInterface/Views/ColorPicker.js:

(WebInspector.ColorPicker.createColorInput):
(WebInspector.ColorPicker):
(WebInspector.ColorPicker.prototype.set color):
(WebInspector.ColorPicker.prototype.set enableColorComponentInputs):
(WebInspector.ColorPicker.prototype._updateColor):
(WebInspector.ColorPicker.prototype._handleFormatChange):
(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 "ColorChanged" event is fired.

  • UserInterface/Controllers/CodeMirrorColorEditingController.js:

(WebInspector.CodeMirrorColorEditingController.prototype.popoverWillPresent):

  • UserInterface/Views/InlineSwatch.js:

(WebInspector.InlineSwatch.prototype._swatchElementClicked):
Add FormatChanged event that fires whenever a new color is set with a different format or
the color value is set for the first time (there is no old format to compare to). This is
needed because if the format becomes RGB, RGBA, HSL, or HSLA from something not in that list
then the size of the containing popover needs to change since the newly added color inputs
will be displayed.

  • UserInterface/Views/GradientEditor.js:

(WebInspector.GradientEditor):
Prevent the color inputs from displaying at all, since there aren't individual swatches for
each color in a gradient.

Location:
trunk/Source/WebInspectorUI
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebInspectorUI/ChangeLog

    r211010 r211057  
     12017-01-23  Devin Rousso  <dcrousso+webkit@gmail.com>
     2
     3        Web Inspector: color picker should feature an editable CSS value
     4        https://bugs.webkit.org/show_bug.cgi?id=124356
     5
     6        Reviewed by Timothy Hatcher.
     7
     8        * UserInterface/Views/ColorPicker.css:
     9        (.color-picker):
     10        (.color-picker.hide-inputs):
     11        (.color-picker > .color-inputs):
     12        (.color-picker > .color-inputs > div):
     13        (.color-picker > .color-inputs > div[hidden]):
     14        (.color-picker > .color-inputs input):
     15
     16        * UserInterface/Views/ColorPicker.js:
     17        (WebInspector.ColorPicker.createColorInput):
     18        (WebInspector.ColorPicker):
     19        (WebInspector.ColorPicker.prototype.set color):
     20        (WebInspector.ColorPicker.prototype.set enableColorComponentInputs):
     21        (WebInspector.ColorPicker.prototype._updateColor):
     22        (WebInspector.ColorPicker.prototype._handleFormatChange):
     23        (WebInspector.ColorPicker.prototype._showColorComponentInputs.updateColorInput):
     24        (WebInspector.ColorPicker.prototype._showColorComponentInputs):
     25        (WebInspector.ColorPicker.prototype._handleColorInputInput):
     26        Add an input element (with a label for the component name and its units) for each component
     27        as part of the current color format (e.g. R, G, B, A).  If any of these inputs are changed
     28        then the color is also changed and the "ColorChanged" event is fired.
     29
     30        * UserInterface/Controllers/CodeMirrorColorEditingController.js:
     31        (WebInspector.CodeMirrorColorEditingController.prototype.popoverWillPresent):
     32        * UserInterface/Views/InlineSwatch.js:
     33        (WebInspector.InlineSwatch.prototype._swatchElementClicked):
     34        Add FormatChanged event that fires whenever a new color is set with a different format or
     35        the color value is set for the first time (there is no old format to compare to).  This is
     36        needed because if the format becomes RGB, RGBA, HSL, or HSLA from something not in that list
     37        then the size of the containing popover needs to change since the newly added color inputs
     38        will be displayed.
     39
     40        * UserInterface/Views/GradientEditor.js:
     41        (WebInspector.GradientEditor):
     42        Prevent the color inputs from displaying at all, since there aren't individual swatches for
     43        each color in a gradient.
     44
    1452017-01-20  Devin Rousso  <dcrousso+webkit@gmail.com>
    246
  • trunk/Source/WebInspectorUI/UserInterface/Controllers/CodeMirrorColorEditingController.js

    r181844 r211057  
    4747        this._colorPicker = new WebInspector.ColorPicker;
    4848        this._colorPicker.addEventListener(WebInspector.ColorPicker.Event.ColorChanged, this._colorPickerColorChanged, this);
     49        this._colorPicker.addEventListener(WebInspector.ColorPicker.Event.FormatChanged, (event) => popover.update());
    4950        popover.content = this._colorPicker.element;
    5051    }
  • trunk/Source/WebInspectorUI/UserInterface/Views/ColorPicker.css

    r210520 r211057  
    2727    position: relative;
    2828    width: 256px;
     29    height: 236px;
     30    padding: 5px;
     31}
     32
     33.color-picker.hide-inputs {
    2934    height: 210px;
    30     padding: 5px;
    3135}
    3236
     
    5458    left: 238px;
    5559}
     60
     61.color-picker > .color-inputs {
     62    display: flex;
     63    justify-content: space-between;
     64    top: 212px;
     65    right: 0;
     66    left: 0;
     67}
     68
     69.color-picker > .color-inputs > div {
     70    display: flex;
     71    align-items: center;
     72    width: 100%;
     73    margin: 0 4px;
     74}
     75
     76.color-picker > .color-inputs > div[hidden] {
     77    display: none;
     78}
     79
     80.color-picker > .color-inputs input {
     81    width: 100%;
     82    margin: 0 0.25em;
     83}
  • trunk/Source/WebInspectorUI/UserInterface/Views/ColorPicker.js

    r210520 r211057  
    4242        this._opacitySlider.element.classList.add("opacity");
    4343
     44        let colorInputsContainerElement = document.createElement("div");
     45        colorInputsContainerElement.classList.add("color-inputs");
     46
     47        function createColorInput(label, {min: min = 0, max: max = 100, step: step = 1, units} = {}) {
     48            let containerElement = colorInputsContainerElement.createChild("div");
     49
     50            containerElement.append(label);
     51
     52            let numberInputElement = containerElement.createChild("input");
     53            numberInputElement.type = "number";
     54            numberInputElement.min = min;
     55            numberInputElement.max = max;
     56            numberInputElement.step = step;
     57            numberInputElement.addEventListener("input", this._handleColorInputInput.bind(this));
     58
     59            if (units && units.length)
     60                containerElement.append(units);
     61
     62            return {containerElement, numberInputElement};
     63        }
     64
     65        this._colorInputs = new Map([
     66            ["R", createColorInput.call(this, "R", {max: 255})],
     67            ["G", createColorInput.call(this, "G", {max: 255})],
     68            ["B", createColorInput.call(this, "B", {max: 255})],
     69            ["H", createColorInput.call(this, "H", {max: 360})],
     70            ["S", createColorInput.call(this, "S", {units: "%"})],
     71            ["L", createColorInput.call(this, "L", {units: "%"})],
     72            ["A", createColorInput.call(this, "A"), {max: 1, step: 0.01}]
     73        ]);
     74
    4475        this._element = document.createElement("div");
    45         this._element.className = "color-picker";
     76        this._element.classList.add("color-picker");
    4677
    4778        this._element.appendChild(this._colorWheel.element);
    4879        this._element.appendChild(this._brightnessSlider.element);
    4980        this._element.appendChild(this._opacitySlider.element);
     81        this._element.appendChild(colorInputsContainerElement);
    5082
    5183        this._opacity = 0;
    5284        this._opacityPattern = "url(Images/Checkers.svg)";
    5385
    54         this._color = "white";
     86        this._color = WebInspector.Color.fromString("white");
    5587
    5688        this._dontUpdateColor = false;
     89
     90        this._enableColorComponentInputs = true;
    5791    }
    5892
     
    96130    set color(color)
    97131    {
     132        console.assert(color instanceof WebInspector.Color);
     133
    98134        this._dontUpdateColor = true;
    99135
    100         this._colorFormat = color.format;
    101 
    102         this._colorWheel.tintedColor = color;
     136        let formatChanged = !this._color || this._color.format !== color.format;
     137
     138        this._color = color;
     139
     140        this._colorWheel.tintedColor = this._color;
    103141        this._brightnessSlider.value = this._colorWheel.brightness;
    104142
    105         this._opacitySlider.value = color.alpha;
    106         this._updateSliders(this._colorWheel.rawColor, color);
     143        this._opacitySlider.value = this._color.alpha;
     144        this._updateSliders(this._colorWheel.rawColor, this._color);
     145
     146        this._showColorComponentInputs();
     147
     148        if (formatChanged)
     149            this._handleFormatChange();
    107150
    108151        this._dontUpdateColor = false;
     152    }
     153
     154    set enableColorComponentInputs(value)
     155    {
     156        this._enableColorComponentInputs = value;
     157
     158        this._showColorComponentInputs();
    109159    }
    110160
     
    130180            return;
    131181
    132         var opacity = Math.round(this._opacity * 100) / 100;
    133 
    134         var components;
    135         if (this._colorFormat === WebInspector.Color.Format.HSL || this._colorFormat === WebInspector.Color.Format.HSLA)
     182        let opacity = Math.round(this._opacity * 100) / 100;
     183
     184        let format = this._color.format;
     185        let components = null;
     186        if (format === WebInspector.Color.Format.HSL || format === WebInspector.Color.Format.HSLA) {
    136187            components = this._colorWheel.tintedColor.hsl.concat(opacity);
    137         else
     188            if (opacity !== 1)
     189                format = WebInspector.Color.Format.HSLA;
     190        } else {
    138191            components = this._colorWheel.tintedColor.rgb.concat(opacity);
    139 
    140         this._color = new WebInspector.Color(this._colorFormat, components);
     192            if (opacity !== 1 && format === WebInspector.Color.Format.RGB)
     193                format = WebInspector.Color.Format.RGBA;
     194        }
     195
     196        let formatChanged = this._color.format === format;
     197
     198        this._color = new WebInspector.Color(format, components);
     199
     200        this._showColorComponentInputs();
     201
    141202        this.dispatchEventToListeners(WebInspector.ColorPicker.Event.ColorChanged, {color: this._color});
     203
     204        if (formatChanged)
     205            this._handleFormatChange();
    142206    }
    143207
     
    151215        this._brightnessSlider.element.style.backgroundImage = "linear-gradient(90deg, black, " + rawColor + ")";
    152216    }
     217
     218    _handleFormatChange()
     219    {
     220        this._element.classList.toggle("hide-inputs", this._color.format !== WebInspector.Color.Format.Keyword
     221            && this._color.format !== WebInspector.Color.Format.RGB
     222            && this._color.format !== WebInspector.Color.Format.RGBA
     223            && this._color.format !== WebInspector.Color.Format.HEX
     224            && this._color.format !== WebInspector.Color.Format.ShortHEX
     225            && this._color.format !== WebInspector.Color.Format.HEXAlpha
     226            && this._color.format !== WebInspector.Color.Format.ShortHEXAlpha
     227            && this._color.format !== WebInspector.Color.Format.HSL
     228            && this._color.format !== WebInspector.Color.Format.HSLA);
     229
     230        this.dispatchEventToListeners(WebInspector.ColorPicker.Event.FormatChanged);
     231    }
     232
     233    _showColorComponentInputs()
     234    {
     235        for (let {containerElement} of this._colorInputs.values())
     236            containerElement.hidden = true;
     237
     238        if (!this._enableColorComponentInputs)
     239            return;
     240
     241        function updateColorInput(key, value) {
     242            let {containerElement, numberInputElement} = this._colorInputs.get(key);
     243            numberInputElement.value = value;
     244            containerElement.hidden = false;
     245        }
     246
     247        switch (this._color.format) {
     248        case WebInspector.Color.Format.RGB:
     249        case WebInspector.Color.Format.RGBA:
     250        case WebInspector.Color.Format.HEX:
     251        case WebInspector.Color.Format.ShortHEX:
     252        case WebInspector.Color.Format.HEXAlpha:
     253        case WebInspector.Color.Format.ShortHEXAlpha:
     254        case WebInspector.Color.Format.Keyword:
     255            var [r, g, b] = this._color.rgb;
     256            updateColorInput.call(this, "R", r);
     257            updateColorInput.call(this, "G", g);
     258            updateColorInput.call(this, "B", b);
     259            break;
     260
     261        case WebInspector.Color.Format.HSL:
     262        case WebInspector.Color.Format.HSLA:
     263            var [h, s, l] = this._color.hsl;
     264            updateColorInput.call(this, "H", h);
     265            updateColorInput.call(this, "S", s);
     266            updateColorInput.call(this, "L", l);
     267            break;
     268
     269        default:
     270            return;
     271        }
     272
     273        if ((this._color.format === WebInspector.Color.Format.Keyword && this._color.alpha !== 1)
     274            || this._color.format === WebInspector.Color.Format.RGBA
     275            || this._color.format === WebInspector.Color.Format.HSLA
     276            || this._color.format === WebInspector.Color.Format.HEXAlpha
     277            || this._color.format === WebInspector.Color.Format.ShortHEXAlpha) {
     278            updateColorInput.call(this, "A", this._color.alpha);
     279        }
     280    }
     281
     282    _handleColorInputInput(event)
     283    {
     284        if (!this._enableColorComponentInputs) {
     285            WebInspector.reportInternalError("Input event fired for disabled color component input");
     286            return;
     287        }
     288
     289        let r = this._colorInputs.get("R").numberInputElement.value;
     290        let g = this._colorInputs.get("G").numberInputElement.value;
     291        let b = this._colorInputs.get("B").numberInputElement.value;
     292        let h = this._colorInputs.get("H").numberInputElement.value;
     293        let s = this._colorInputs.get("S").numberInputElement.value;
     294        let l = this._colorInputs.get("L").numberInputElement.value;
     295        let a = this._colorInputs.get("A").numberInputElement.value;
     296
     297        let colorString = "";
     298        let oldFormat = this._color.format;
     299
     300        switch (oldFormat) {
     301        case WebInspector.Color.Format.RGB:
     302        case WebInspector.Color.Format.HEX:
     303        case WebInspector.Color.Format.ShortHEX:
     304        case WebInspector.Color.Format.Keyword:
     305            colorString = `rgb(${r}, ${g}, ${b})`;
     306            break;
     307
     308        case WebInspector.Color.Format.RGBA:
     309        case WebInspector.Color.Format.HEXAlpha:
     310        case WebInspector.Color.Format.ShortHEXAlpha:
     311            colorString = `rgba(${r}, ${g}, ${b}, ${a})`;
     312            break;
     313
     314        case WebInspector.Color.Format.HSL:
     315            colorString = `hsl(${h}, ${s}%, ${l}%)`;
     316            break;
     317
     318        case WebInspector.Color.Format.HSLA:
     319            colorString = `hsla(${h}, ${s}%, ${l}%, ${a})`;
     320            break;
     321
     322        default:
     323            WebInspector.reportInternalError(`Input event fired for invalid color format "${this._color.format}"`);
     324            return;
     325        }
     326
     327        this.color = WebInspector.Color.fromString(colorString);
     328        this._color.format = oldFormat;
     329
     330        this.dispatchEventToListeners(WebInspector.ColorPicker.Event.ColorChanged, {color: this._color});
     331    }
    153332};
    154333
    155334WebInspector.ColorPicker.Event = {
    156     ColorChanged: "css-color-picker-color-changed"
     335    ColorChanged: "css-color-picker-color-changed",
     336    FormatChanged: "css-color-picker-format-changed",
    157337};
  • trunk/Source/WebInspectorUI/UserInterface/Views/GradientEditor.js

    r205425 r211057  
    7373        this._colorPicker = new WebInspector.ColorPicker;
    7474        this._colorPicker.colorWheel.dimension = 190;
     75        this._colorPicker.enableColorComponentInputs = false;
    7576        this._colorPicker.addEventListener(WebInspector.ColorPicker.Event.ColorChanged, this._colorPickerColorChanged, this);
    7677
  • trunk/Source/WebInspectorUI/UserInterface/Views/InlineSwatch.js

    r206729 r211057  
    166166            this._valueEditor = new WebInspector.ColorPicker;
    167167            this._valueEditor.addEventListener(WebInspector.ColorPicker.Event.ColorChanged, this._valueEditorValueDidChange, this);
     168            this._valueEditor.addEventListener(WebInspector.ColorPicker.Event.FormatChanged, (event) => popover.update());
    168169        }
    169170
Note: See TracChangeset for help on using the changeset viewer.