Changeset 287409 in webkit


Ignore:
Timestamp:
Dec 23, 2021 12:54:21 PM (7 months ago)
Author:
ntim@apple.com
Message:

Web Inspector: Support conic gradients in gradient editor and autocompletion
https://bugs.webkit.org/show_bug.cgi?id=234562

Reviewed by Devin Rousso.

  • Localizations/en.lproj/localizedStrings.js:
  • UserInterface/Controllers/CSSManager.js:
  • UserInterface/Models/Gradient.js:

(WI.Gradient.angleFromString):
(WI.Gradient.fromString):
(WI.Gradient.prototype.get angleValue):
(WI.Gradient.prototype.set angleValue):
(WI.Gradient.prototype.get angleUnits):
(WI.Gradient.prototype.set angleUnits):
(WI.Gradient.prototype._angleValueForUnits):
(WI.Gradient):
(WI.LinearGradient.fromComponents):
(WI.LinearGradient.prototype.toString):
(WI.LinearGradient):
(WI.RadialGradient):
(WI.RadialGradient.fromComponents):
(WI.RadialGradient.prototype.get angleValue):
(WI.RadialGradient.prototype.set angleValue):
(WI.RadialGradient.prototype.get angleUnits):
(WI.RadialGradient.prototype.set angleUnits):
(WI.RadialGradient.prototype.copy):
(WI.RadialGradient.prototype.toString):
(WI.ConicGradient):
(WI.ConicGradient.fromComponents):
(WI.ConicGradient.prototype.copy):
(WI.ConicGradient.prototype.toString):
(WI.LinearGradient.prototype.set angleValue): Deleted.
(WI.LinearGradient.prototype.get angleValue): Deleted.
(WI.LinearGradient.prototype.set angleUnits): Deleted.
(WI.LinearGradient.prototype.get angleUnits): Deleted.
(WI.LinearGradient.prototype._angleValueForUnits): Deleted.

  • UserInterface/Views/CodeMirrorTextMarkers.js:
  • UserInterface/Views/GradientEditor.js:

(WI.GradientEditor):
(WI.GradientEditor.prototype.set gradient):
(WI.GradientEditor.prototype._gradientTypeChanged):

  • UserInterface/Views/SpreadsheetStyleProperty.js:

(WI.SpreadsheetStyleProperty.prototype._addGradientTokens):

Location:
trunk/Source/WebInspectorUI
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebInspectorUI/ChangeLog

    r287408 r287409  
     12021-12-23  Tim Nguyen  <ntim@apple.com>
     2
     3        Web Inspector: Support conic gradients in gradient editor and autocompletion
     4        https://bugs.webkit.org/show_bug.cgi?id=234562
     5
     6        Reviewed by Devin Rousso.
     7
     8        * Localizations/en.lproj/localizedStrings.js:
     9        * UserInterface/Controllers/CSSManager.js:
     10        * UserInterface/Models/Gradient.js:
     11        (WI.Gradient.angleFromString):
     12        (WI.Gradient.fromString):
     13        (WI.Gradient.prototype.get angleValue):
     14        (WI.Gradient.prototype.set angleValue):
     15        (WI.Gradient.prototype.get angleUnits):
     16        (WI.Gradient.prototype.set angleUnits):
     17        (WI.Gradient.prototype._angleValueForUnits):
     18        (WI.Gradient):
     19        (WI.LinearGradient.fromComponents):
     20        (WI.LinearGradient.prototype.toString):
     21        (WI.LinearGradient):
     22        (WI.RadialGradient):
     23        (WI.RadialGradient.fromComponents):
     24        (WI.RadialGradient.prototype.get angleValue):
     25        (WI.RadialGradient.prototype.set angleValue):
     26        (WI.RadialGradient.prototype.get angleUnits):
     27        (WI.RadialGradient.prototype.set angleUnits):
     28        (WI.RadialGradient.prototype.copy):
     29        (WI.RadialGradient.prototype.toString):
     30        (WI.ConicGradient):
     31        (WI.ConicGradient.fromComponents):
     32        (WI.ConicGradient.prototype.copy):
     33        (WI.ConicGradient.prototype.toString):
     34        (WI.LinearGradient.prototype.set angleValue): Deleted.
     35        (WI.LinearGradient.prototype.get angleValue): Deleted.
     36        (WI.LinearGradient.prototype.set angleUnits): Deleted.
     37        (WI.LinearGradient.prototype.get angleUnits): Deleted.
     38        (WI.LinearGradient.prototype._angleValueForUnits): Deleted.
     39        * UserInterface/Views/CodeMirrorTextMarkers.js:
     40        * UserInterface/Views/GradientEditor.js:
     41        (WI.GradientEditor):
     42        (WI.GradientEditor.prototype.set gradient):
     43        (WI.GradientEditor.prototype._gradientTypeChanged):
     44        * UserInterface/Views/SpreadsheetStyleProperty.js:
     45        (WI.SpreadsheetStyleProperty.prototype._addGradientTokens):
     46
    1472021-12-23  Tim Nguyen  <ntim@apple.com>
    248
  • trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js

    r286876 r287409  
    368368localizedStrings["Connection ID"] = "Connection ID";
    369369localizedStrings["Connection:"] = "Connection:";
     370localizedStrings["Conic Gradient"] = "Conic Gradient";
    370371localizedStrings["Console"] = "Console";
    371372localizedStrings["Console Evaluation"] = "Console Evaluation";
     
    11841185localizedStrings["Repeating Linear Gradient"] = "Repeating Linear Gradient";
    11851186localizedStrings["Repeating Radial Gradient"] = "Repeating Radial Gradient";
     1187localizedStrings["Repeating Conic Gradient"] = "Repeating Conic Gradient";
    11861188localizedStrings["Request"] = "Request";
    11871189localizedStrings["Request & Response"] = "Request & Response";
  • trunk/Source/WebInspectorUI/UserInterface/Controllers/CSSManager.js

    r286844 r287409  
    111111            for (let color of WI.CSSKeywordCompletions._colors)
    112112                colorKeywordsForCodeMirror[nameForCodeMirror(color)] = true;
     113
     114            // TODO: Remove these keywords once they are built-in codemirror or once we get values from WebKit itself.
     115            valueKeywordsForCodeMirror["conic-gradient"] = true;
     116            valueKeywordsForCodeMirror["repeating-conic-gradient"] = true;
    113117
    114118            function updateCodeMirrorCSSMode(mimeType) {
  • trunk/Source/WebInspectorUI/UserInterface/Models/Gradient.js

    r259368 r287409  
    11/*
    2  * Copyright (C) 2014 Apple Inc. All rights reserved.
     2 * Copyright (C) 2014, 2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3434    // Static
    3535
     36    static angleFromString(string)
     37    {
     38        let match = string.match(/([-\d\.]+)(\w+)/);
     39        if (!match || !Object.values(WI.Gradient.AngleUnits).includes(match[2]))
     40            return null;
     41
     42        return {value: parseFloat(match[1]), units: match[2]};
     43    }
     44
    3645    static fromString(cssString)
    3746    {
     
    3948        var openingParenthesisIndex = cssString.indexOf("(");
    4049        var typeString = cssString.substring(0, openingParenthesisIndex);
    41         if (typeString.indexOf(WI.Gradient.Types.Linear) !== -1)
     50        if (typeString.includes(WI.Gradient.Types.Linear))
    4251            type = WI.Gradient.Types.Linear;
    43         else if (typeString.indexOf(WI.Gradient.Types.Radial) !== -1)
     52        else if (typeString.includes(WI.Gradient.Types.Radial))
    4453            type = WI.Gradient.Types.Radial;
     54        else if (typeString.includes(WI.Gradient.Types.Conic))
     55            type = WI.Gradient.Types.Conic;
    4556        else
    4657            return null;
     
    89100            return null;
    90101
    91         var gradient;
    92         if (type === WI.Gradient.Types.Linear)
     102        let gradient = null;
     103        switch (type) {
     104        case WI.Gradient.Types.Linear:
    93105            gradient = WI.LinearGradient.fromComponents(components);
    94         else
     106            break;
     107
     108        case WI.Gradient.Types.Radial:
    95109            gradient = WI.RadialGradient.fromComponents(components);
     110            break;
     111
     112        case WI.Gradient.Types.Conic:
     113            gradient = WI.ConicGradient.fromComponents(components);
     114            break;
     115        }
    96116
    97117        if (gradient)
     
    150170    // Public
    151171
     172    get angleValue()
     173    {
     174        return this._angle.value.maxDecimals(2);
     175    }
     176
     177    set angleValue(value)
     178    {
     179        this._angle.value = value;
     180    }
     181
     182    get angleUnits()
     183    {
     184        return this._angle.units;
     185    }
     186
     187    set angleUnits(units)
     188    {
     189        if (units === this._angle.units)
     190            return;
     191
     192        this._angle.value = this._angleValueForUnits(units);
     193        this._angle.units = units;
     194    }
     195
    152196    copy()
    153197    {
     
    158202    {
    159203        // Implemented by subclasses.
     204    }
     205
     206    // Private
     207
     208    _angleValueForUnits(units)
     209    {
     210        if (units === this._angle.units)
     211            return this._angle.value;
     212
     213        let deg = 0;
     214
     215        switch (this._angle.units) {
     216        case WI.Gradient.AngleUnits.DEG:
     217            deg = this._angle.value;
     218            break;
     219
     220        case WI.Gradient.AngleUnits.RAD:
     221            deg = this._angle.value * 180 / Math.PI;
     222            break;
     223
     224        case WI.Gradient.AngleUnits.GRAD:
     225            deg = this._angle.value / 400 * 360;
     226            break;
     227
     228        case WI.Gradient.AngleUnits.TURN:
     229            deg = this._angle.value * 360;
     230            break;
     231        }
     232
     233        switch (units) {
     234        case WI.Gradient.AngleUnits.DEG:
     235            return deg;
     236
     237        case WI.Gradient.AngleUnits.RAD:
     238            return deg * Math.PI / 180;
     239
     240        case WI.Gradient.AngleUnits.GRAD:
     241            return deg / 360 * 400;
     242
     243        case WI.Gradient.AngleUnits.TURN:
     244            return deg / 360;
     245        }
     246
     247        return 0;
    160248    }
    161249};
     
    163251WI.Gradient.Types = {
    164252    Linear: "linear-gradient",
    165     Radial: "radial-gradient"
     253    Radial: "radial-gradient",
     254    Conic: "conic-gradient",
     255};
     256
     257WI.Gradient.AngleUnits = {
     258    DEG: "deg",
     259    RAD: "rad",
     260    GRAD: "grad",
     261    TURN: "turn",
    166262};
    167263
     
    178274    static fromComponents(components)
    179275    {
    180         let angle = {value: 180, units: WI.LinearGradient.AngleUnits.DEG};
     276        let angle = {value: 180, units: WI.Gradient.AngleUnits.DEG};
    181277
    182278        if (components[0].length === 1 && !WI.Color.fromString(components[0][0])) {
    183             let match = components[0][0].match(/([-\d\.]+)(\w+)/);
    184             if (!match || !Object.values(WI.LinearGradient.AngleUnits).includes(match[2]))
     279            angle = WI.Gradient.angleFromString(components[0][0]);
     280
     281            if (!angle)
    185282                return null;
    186 
    187             angle.value = parseFloat(match[1]);
    188             angle.units = match[2];
    189283
    190284            components.shift();
     
    227321        }
    228322
    229         var stops = WI.Gradient.stopsWithComponents(components);
     323        let stops = WI.Gradient.stopsWithComponents(components);
    230324        if (!stops)
    231325            return null;
     
    233327        return new WI.LinearGradient(angle, stops);
    234328    }
    235 
    236     // Public
    237 
    238     set angleValue(value) { this._angle.value = value; }
    239 
    240     get angleValue()
    241     {
    242         return this._angle.value.maxDecimals(2);
    243     }
    244 
    245     set angleUnits(units)
    246     {
    247         if (units === this._angle.units)
    248             return;
    249 
    250         this._angle.value = this._angleValueForUnits(units);
    251         this._angle.units = units;
    252     }
    253 
    254     get angleUnits() { return this._angle.units; }
    255329
    256330    copy()
     
    281355            str += this.angleValue + this.angleUnits;
    282356
    283         if (str !== "")
     357        if (str)
    284358            str += ", ";
    285359
     
    288362        return (this.repeats ? "repeating-" : "") + this.type + "(" + str + ")";
    289363    }
    290 
    291     // Private
    292 
    293     _angleValueForUnits(units)
    294     {
    295         if (units === this._angle.units)
    296             return this._angle.value;
    297 
    298         let deg = 0;
    299 
    300         switch (this._angle.units) {
    301         case WI.LinearGradient.AngleUnits.DEG:
    302             deg = this._angle.value;
    303             break;
    304 
    305         case WI.LinearGradient.AngleUnits.RAD:
    306             deg = this._angle.value * 180 / Math.PI;
    307             break;
    308 
    309         case WI.LinearGradient.AngleUnits.GRAD:
    310             deg = this._angle.value / 400 * 360;
    311             break;
    312 
    313         case WI.LinearGradient.AngleUnits.TURN:
    314             deg = this._angle.value * 360;
    315             break;
    316 
    317         default:
    318             WI.reportInternalError(`Unknown angle units "${this._angle.units}"`);
    319             return 0;
    320         }
    321 
    322         let value = 0;
    323 
    324         switch (units) {
    325         case WI.LinearGradient.AngleUnits.DEG:
    326             value = deg;
    327             break;
    328 
    329         case WI.LinearGradient.AngleUnits.RAD:
    330             value = deg * Math.PI / 180;
    331             break;
    332 
    333         case WI.LinearGradient.AngleUnits.GRAD:
    334             value = deg / 360 * 400;
    335             break;
    336 
    337         case WI.LinearGradient.AngleUnits.TURN:
    338             value = deg / 360;
    339             break;
    340         }
    341 
    342         return value;
    343     }
    344 };
    345 
    346 WI.LinearGradient.AngleUnits = {
    347     DEG: "deg",
    348     RAD: "rad",
    349     GRAD: "grad",
    350     TURN: "turn",
    351364};
    352365
     
    363376    static fromComponents(components)
    364377    {
    365         var sizing = !WI.Color.fromString(components[0].join(" ")) ? components.shift().join(" ") : "";
    366 
    367         var stops = WI.Gradient.stopsWithComponents(components);
     378        let sizing = !WI.Color.fromString(components[0].join(" ")) ? components.shift().join(" ") : "";
     379
     380        let stops = WI.Gradient.stopsWithComponents(components);
    368381        if (!stops)
    369382            return null;
     
    374387    // Public
    375388
     389    get angleValue()
     390    {
     391        return 0;
     392    }
     393
     394    set angleValue(value)
     395    {
     396        console.assert(false, "CSS conic gradients do not have an angle");
     397    }
     398
     399    get angleUnits()
     400    {
     401        return "";
     402    }
     403
     404    set angleUnits(units)
     405    {
     406        console.assert(false, "CSS conic gradients do not have an angle");
     407    }
     408
    376409    copy()
    377410    {
     
    381414    toString()
    382415    {
    383         var str = this.sizing;
    384 
    385         if (str !== "")
     416        let str = this.sizing;
     417
     418        if (str)
    386419            str += ", ";
    387420
     
    391424    }
    392425};
     426
     427WI.ConicGradient = class ConicGradient extends WI.Gradient
     428{
     429    constructor(angle, position, stops)
     430    {
     431        super(WI.Gradient.Types.Conic, stops);
     432
     433        this._angle = angle;
     434        this._position = position;
     435    }
     436
     437    // Static
     438
     439    static fromComponents(components)
     440    {
     441        let angle = {value: 0, units: WI.Gradient.AngleUnits.DEG};
     442        let position = null;
     443        let hasCustomAngleOrPosition = false;
     444
     445        if (components[0][0] == "from") {
     446            components[0].shift();
     447            angle = WI.Gradient.angleFromString(components[0][0]);
     448            if (!angle)
     449                return null;
     450            components[0].shift();
     451            hasCustomAngleOrPosition = true;
     452        }
     453        if (components[0][0] == "at") {
     454            components[0].shift();
     455            // FIXME: <https://webkit.org/b/234643> (Web Inspector: allow editing positions in gradient editor)
     456            if (components[0].length <= 0)
     457                return null;
     458            position = components[0].join(" ");
     459            hasCustomAngleOrPosition = true;
     460        }
     461        if (hasCustomAngleOrPosition)
     462            components.shift();
     463
     464        let stops = WI.Gradient.stopsWithComponents(components);
     465        if (!stops)
     466            return null;
     467
     468        return new WI.ConicGradient(angle, position, stops);
     469    }
     470
     471    // Public
     472
     473    copy()
     474    {
     475        return new WI.ConicGradient(this._angle, this._position, this.stops.concat());
     476    }
     477
     478    toString()
     479    {
     480        let str = "";
     481
     482        if (this._angle.value)
     483            str += `from ${this._angle.value}${this._angle.units}`;
     484
     485        if (this._position) {
     486            if (str)
     487                str += " ";
     488            str += `at ${this._position}`;
     489        }
     490
     491        if (str)
     492            str += ", ";
     493
     494        str += this.stringFromStops(this.stops);
     495
     496        return (this.repeats ? "repeating-" : "") + this.type + "(" + str + ")";
     497    }
     498};
  • trunk/Source/WebInspectorUI/UserInterface/Views/CodeMirrorTextMarkers.js

    r242602 r287409  
    112112        }
    113113
    114         if (/(repeating-)?(linear|radial)-gradient$/.test(lineContent.substring(0, index)))
     114        if (/(repeating-)?(linear|radial|conic)-gradient$/.test(lineContent.substring(0, index)))
    115115            return false;
    116116
     
    129129    var end = range instanceof WI.TextRange ? range.endLine + 1 : codeMirror.lineCount();
    130130
    131     var gradientRegex = /(repeating-)?(linear|radial)-gradient\s*\(\s*/g;
     131    var gradientRegex = /(repeating-)?(linear|radial|conic)-gradient\s*\(\s*/g;
    132132
    133133    for (var lineNumber = start; lineNumber < end; ++lineNumber) {
  • trunk/Source/WebInspectorUI/UserInterface/Views/GradientEditor.js

    r253859 r287409  
    11/*
    2  * Copyright (C) 2014 Apple Inc. All rights reserved.
     2 * Copyright (C) 2014, 2021 Apple Inc. All rights reserved.
    33 * Copyright (C) 2015 Devin Rousso <webkit@devinrousso.com>. All rights reserved.
    44 *
     
    4646                repeats: false
    4747            },
     48            "conic-gradient": {
     49                type: WI.ConicGradient,
     50                label: WI.UIString("Conic Gradient"),
     51                repeats: false
     52            },
    4853            "repeating-linear-gradient": {
    4954                type: WI.LinearGradient,
     
    5560                label: WI.UIString("Repeating Radial Gradient"),
    5661                repeats: true
    57             }
     62            },
     63            "repeating-conic-gradient": {
     64                type: WI.ConicGradient,
     65                label: WI.UIString("Repeating Conic Gradient"),
     66                repeats: true
     67            },
    5868        };
    5969        this._editingColor = false;
     
    94104
    95105        const angleUnitsData = [
    96             {name: WI.LinearGradient.AngleUnits.DEG, min: 0, max: 360, step: 1},
    97             {name: WI.LinearGradient.AngleUnits.RAD, min: 0, max: 2 * Math.PI, step: 0.01},
    98             {name: WI.LinearGradient.AngleUnits.GRAD, min: 0, max: 400, step: 1},
    99             {name: WI.LinearGradient.AngleUnits.TURN, min: 0, max: 1, step: 0.01}
     106            {name: WI.Gradient.AngleUnits.DEG, min: 0, max: 360, step: 1},
     107            {name: WI.Gradient.AngleUnits.RAD, min: 0, max: 2 * Math.PI, step: 0.01},
     108            {name: WI.Gradient.AngleUnits.GRAD, min: 0, max: 400, step: 1},
     109            {name: WI.Gradient.AngleUnits.TURN, min: 0, max: 1, step: 0.01}
    100110        ];
    101111
     
    120130        const isLinear = gradient instanceof WI.LinearGradient;
    121131        const isRadial = gradient instanceof WI.RadialGradient;
    122         console.assert(isLinear || isRadial);
    123         if (!isLinear && !isRadial)
     132        const isConic = gradient instanceof WI.ConicGradient;
     133        console.assert(isLinear || isRadial || isConic);
     134        if (!isLinear && !isRadial && !isConic)
    124135            return;
    125136
     
    128139        if (isLinear) {
    129140            this._gradientTypePicker.value = this._gradient.repeats ? "repeating-linear-gradient" : "linear-gradient";
    130 
    131141            this._angleUnitsChanged();
    132         } else
     142        } else if (isRadial)
    133143            this._gradientTypePicker.value = this._gradient.repeats ? "repeating-radial-gradient" : "radial-gradient";
     144        else {
     145            this._gradientTypePicker.value = this._gradient.repeats ? "repeating-conic-gradient" : "conic-gradient";
     146            this._angleUnitsChanged();
     147        }
    134148
    135149        this._updateCSSClassForGradientType();
     
    186200        const descriptor = this._gradientTypes[this._gradientTypePicker.value];
    187201        if (!(this._gradient instanceof descriptor.type)) {
    188             if (descriptor.type === WI.LinearGradient) {
    189                 this._gradient = new WI.LinearGradient({value: 180, units: WI.LinearGradient.AngleUnits.DEG}, this._gradient.stops);
    190 
     202            switch (descriptor.type) {
     203            case WI.LinearGradient:
     204                this._gradient = new WI.LinearGradient({value: 180, units: WI.Gradient.AngleUnits.DEG}, this._gradient.stops);
    191205                this._angleUnitsChanged();
    192             } else
     206                break;
     207            case WI.RadialGradient:
    193208                this._gradient = new WI.RadialGradient("", this._gradient.stops);
     209                break;
     210            case WI.ConicGradient:
     211                this._gradient = new WI.ConicGradient({value: 0, units: WI.Gradient.AngleUnits.DEG}, null, this._gradient.stops);
     212                this._angleUnitsChanged();
     213                break;
     214            }
    194215
    195216            this._updateCSSClassForGradientType();
  • trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetStyleProperty.js

    r286875 r287409  
    649649    _addGradientTokens(tokens)
    650650    {
    651         let gradientRegex = /^(repeating-)?(linear|radial)-gradient$/i;
     651        let gradientRegex = /^(repeating-)?(linear|radial|conic)-gradient$/i;
    652652        let newTokens = [];
    653653        let gradientStartIndex = NaN;
Note: See TracChangeset for help on using the changeset viewer.