Changeset 248202 in webkit


Ignore:
Timestamp:
Aug 3, 2019 12:36:32 PM (5 years ago)
Author:
Devin Rousso
Message:

Web Inspector: Elements: Styles: add icons for various CSS rule types
https://bugs.webkit.org/show_bug.cgi?id=199946

Reviewed by Joseph Pecoraro.

Source/WebInspectorUI:

  • UserInterface/Controllers/CSSManager.js:

(WI.CSSManager.displayNameForPseudoId):
Add hardcoded pseudo-selector identifiers for older backends.

  • UserInterface/Models/CSSSelector.js:

(WI.CSSSelector.prototype.isPseudoSelector): Added.
(WI.CSSSelector.prototype.isPseudoElementSelector): Deleted.
There are more types of pseudo-selectors than just :{before|after}.

  • UserInterface/Models/CSSStyleDeclaration.js:

(WI.CSSStyleDeclaration.prototype.generateCSSRuleString): Added.

  • UserInterface/Views/SpreadsheetRulesStyleDetailsPanel.js:

(WI.SpreadsheetRulesStyleDetailsPanel.prototype.spreadsheetCSSStyleDeclarationSectionAddNewRule): Added.
(WI.SpreadsheetRulesStyleDetailsPanel.prototype.layout):
Provide a delegate method for adding a new rule, so the WI.SpreadsheetRulesStyleDetailsPanel
can know what selector to focus once the new rule gets added.

  • UserInterface/Views/SpreadsheetCSSStyleDeclarationSection.js:

(WI.SpreadsheetCSSStyleDeclarationSection.prototype.initialLayout):
(WI.SpreadsheetCSSStyleDeclarationSection.prototype._renderSelector):
(WI.SpreadsheetCSSStyleDeclarationSection.prototype._populateIconElementContextMenu): Added.

  • UserInterface/Views/SpreadsheetCSSStyleDeclarationSection.css:

(.spreadsheet-css-declaration .header.editing-selector .selector): Added.
(.spreadsheet-css-declaration .selector > .icon): Added.
(.spreadsheet-css-declaration .selector > .icon + *): Added.
(.spreadsheet-css-declaration .selector.style-attribute > span): Added.
When "mousedown" (or "contextmenu") on the icon, show a context menu with helpful actions:

  • Copy Rule
  • {Disable|Enable} Rule
  • Duplicate Selector
  • Add :{active|focus|hover|visited} Rule
  • Create ::{before|after} Rule
  • Reveal in {Resources Tab|Sources Tab|Stylesheet}

Drive-by: add an extra 0.5px of initial margin before the Style Attribute selector (which is
sans-serif) so it properly aligns with the other selectors (which are monospaced).

  • UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.js:

(WI.SpreadsheetCSSStyleDeclarationEditor.prototype.layout):

  • UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.css:

(.spreadsheet-style-declaration-editor:empty): Added.
(.spreadsheet-style-declaration-editor.no-properties): Deleted.
Add some extra space when there's no inline style so it looks a bit less cramped.

  • UserInterface/Main.html:
  • UserInterface/Views/StyleRuleIcons.css: Added.

(.author-style-rule-icon .icon):
(.author-style-rule-icon.pseudo-selector .icon):
(.user-style-rule-icon .icon):
(.user-style-rule-icon.pseudo-selector .icon):
(.user-agent-style-rule-icon .icon):
(.user-agent-style-rule-icon.pseudo-selector .icon):
(.inspector-style-rule-icon .icon):
(.inspector-style-rule-icon.pseudo-selector .icon):
(.inherited-style-rule-icon .icon):
(.inherited-element-style-rule-icon .icon):

  • UserInterface/Images/StyleRule.svg: Added.
  • UserInterface/Images/StyleRuleInheritedElement.svg: Added.
  • UserInterface/Images/StyleRulePseudo.svg: Added.

Add generic icon classes for style rule icons.

  • UserInterface/Base/Setting.js:
  • UserInterface/Views/SettingsTabContentView.js:

(WI.SettingsTabContentView.prototype._createExperimentalSettingsView):
Add experimental setting.

  • Localizations/en.lproj/localizedStrings.js:

LayoutTests:

  • inspector/css/generateCSSRuleString.html: Added.
  • inspector/css/generateCSSRuleString-expected.txt: Added.
Location:
trunk
Files:
5 added
14 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r248201 r248202  
     12019-08-03  Devin Rousso  <drousso@apple.com>
     2
     3        Web Inspector: Elements: Styles: add icons for various CSS rule types
     4        https://bugs.webkit.org/show_bug.cgi?id=199946
     5
     6        Reviewed by Joseph Pecoraro.
     7
     8        * inspector/css/generateCSSRuleString.html: Added.
     9        * inspector/css/generateCSSRuleString-expected.txt: Added.
     10
    1112019-08-03  Devin Rousso  <drousso@apple.com>
    212
  • trunk/Source/WebInspectorUI/ChangeLog

    r248201 r248202  
     12019-08-03  Devin Rousso  <drousso@apple.com>
     2
     3        Web Inspector: Elements: Styles: add icons for various CSS rule types
     4        https://bugs.webkit.org/show_bug.cgi?id=199946
     5
     6        Reviewed by Joseph Pecoraro.
     7
     8        * UserInterface/Controllers/CSSManager.js:
     9        (WI.CSSManager.displayNameForPseudoId):
     10        Add hardcoded pseudo-selector identifiers for older backends.
     11
     12        * UserInterface/Models/CSSSelector.js:
     13        (WI.CSSSelector.prototype.isPseudoSelector): Added.
     14        (WI.CSSSelector.prototype.isPseudoElementSelector): Deleted.
     15        There are more types of pseudo-selectors than just `:{before|after}`.
     16
     17        * UserInterface/Models/CSSStyleDeclaration.js:
     18        (WI.CSSStyleDeclaration.prototype.generateCSSRuleString): Added.
     19
     20        * UserInterface/Views/SpreadsheetRulesStyleDetailsPanel.js:
     21        (WI.SpreadsheetRulesStyleDetailsPanel.prototype.spreadsheetCSSStyleDeclarationSectionAddNewRule): Added.
     22        (WI.SpreadsheetRulesStyleDetailsPanel.prototype.layout):
     23        Provide a delegate method for adding a new rule, so the `WI.SpreadsheetRulesStyleDetailsPanel`
     24        can know what selector to focus once the new rule gets added.
     25
     26        * UserInterface/Views/SpreadsheetCSSStyleDeclarationSection.js:
     27        (WI.SpreadsheetCSSStyleDeclarationSection.prototype.initialLayout):
     28        (WI.SpreadsheetCSSStyleDeclarationSection.prototype._renderSelector):
     29        (WI.SpreadsheetCSSStyleDeclarationSection.prototype._populateIconElementContextMenu): Added.
     30        * UserInterface/Views/SpreadsheetCSSStyleDeclarationSection.css:
     31        (.spreadsheet-css-declaration .header.editing-selector .selector): Added.
     32        (.spreadsheet-css-declaration .selector > .icon): Added.
     33        (.spreadsheet-css-declaration .selector > .icon + *): Added.
     34        (.spreadsheet-css-declaration .selector.style-attribute > span): Added.
     35        When "mousedown" (or "contextmenu") on the icon, show a context menu with helpful actions:
     36         - Copy Rule
     37         - {Disable|Enable} Rule
     38         - Duplicate Selector
     39         - Add :{active|focus|hover|visited} Rule
     40         - Create ::{before|after} Rule
     41         - Reveal in {Resources Tab|Sources Tab|Stylesheet}
     42        Drive-by: add an extra 0.5px of initial margin before the Style Attribute selector (which is
     43        sans-serif) so it properly aligns with the other selectors (which are monospaced).
     44
     45        * UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.js:
     46        (WI.SpreadsheetCSSStyleDeclarationEditor.prototype.layout):
     47        * UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.css:
     48        (.spreadsheet-style-declaration-editor:empty): Added.
     49        (.spreadsheet-style-declaration-editor.no-properties): Deleted.
     50        Add some extra space when there's no inline style so it looks a bit less cramped.
     51
     52        * UserInterface/Main.html:
     53        * UserInterface/Views/StyleRuleIcons.css: Added.
     54        (.author-style-rule-icon .icon):
     55        (.author-style-rule-icon.pseudo-selector .icon):
     56        (.user-style-rule-icon .icon):
     57        (.user-style-rule-icon.pseudo-selector .icon):
     58        (.user-agent-style-rule-icon .icon):
     59        (.user-agent-style-rule-icon.pseudo-selector .icon):
     60        (.inspector-style-rule-icon .icon):
     61        (.inspector-style-rule-icon.pseudo-selector .icon):
     62        (.inherited-style-rule-icon .icon):
     63        (.inherited-element-style-rule-icon .icon):
     64        * UserInterface/Images/StyleRule.svg: Added.
     65        * UserInterface/Images/StyleRuleInheritedElement.svg: Added.
     66        * UserInterface/Images/StyleRulePseudo.svg: Added.
     67        Add generic icon classes for style rule icons.
     68
     69        * UserInterface/Base/Setting.js:
     70        * UserInterface/Views/SettingsTabContentView.js:
     71        (WI.SettingsTabContentView.prototype._createExperimentalSettingsView):
     72        Add experimental setting.
     73
     74        * Localizations/en.lproj/localizedStrings.js:
     75
    1762019-08-03  Devin Rousso  <drousso@apple.com>
    277
  • trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js

    r248201 r248202  
    8383localizedStrings["Activity Viewer"] = "Activity Viewer";
    8484localizedStrings["Add"] = "Add";
     85localizedStrings["Add %s Rule"] = "Add %s Rule";
    8586localizedStrings["Add Action"] = "Add Action";
    8687localizedStrings["Add Breakpoint"] = "Add Breakpoint";
     
    292293localizedStrings["Copy Path to Property"] = "Copy Path to Property";
    293294localizedStrings["Copy Row"] = "Copy Row";
     295localizedStrings["Copy Rule"] = "Copy Rule";
    294296localizedStrings["Copy Selected"] = "Copy Selected";
    295297localizedStrings["Copy Table"] = "Copy Table";
     
    297299localizedStrings["Could not fetch properties. Object may no longer exist."] = "Could not fetch properties. Object may no longer exist.";
    298300localizedStrings["Count"] = "Count";
     301localizedStrings["Create %s Rule"] = "Create %s Rule";
    299302localizedStrings["Create Breakpoint"] = "Create Breakpoint";
    300303localizedStrings["Create a new tab"] = "Create a new tab";
     
    345348localizedStrings["Disable ICE Candidate Restrictions"] = "Disable ICE Candidate Restrictions";
    346349localizedStrings["Disable Program"] = "Disable Program";
     350localizedStrings["Disable Rule"] = "Disable Rule";
    347351localizedStrings["Disable all breakpoints (%s)"] = "Disable all breakpoints (%s)";
    348352localizedStrings["Disable paint flashing"] = "Disable paint flashing";
     
    366370localizedStrings["Dropped Element"] = "Dropped Element";
    367371localizedStrings["Dropped Node"] = "Dropped Node";
     372localizedStrings["Duplicate Selector"] = "Duplicate Selector";
    368373localizedStrings["Duplicate property"] = "Duplicate property";
    369374localizedStrings["Duration"] = "Duration";
     
    421426localizedStrings["Enable New Tab Bar"] = "Enable New Tab Bar";
    422427localizedStrings["Enable Program"] = "Enable Program";
     428localizedStrings["Enable Rule"] = "Enable Rule";
    423429localizedStrings["Enable Sources Tab"] = "Enable Sources Tab";
    424430localizedStrings["Enable all breakpoints (%s)"] = "Enable all breakpoints (%s)";
     
    906912localizedStrings["Reveal in Resources Tab"] = "Reveal in Resources Tab";
    907913localizedStrings["Reveal in Sources Tab"] = "Reveal in Sources Tab";
     914localizedStrings["Reveal in Stylesheet"] = "Reveal in Stylesheet";
    908915localizedStrings["Role"] = "Role";
    909916localizedStrings["Run %d"] = "Run %d";
     
    980987localizedStrings["Show Elements"] = "Show Elements";
    981988localizedStrings["Show Grid"] = "Show Grid";
     989localizedStrings["Show Icons"] = "Show Icons";
    982990localizedStrings["Show Jump to Effective Property Button"] = "Show Jump to Effective Property Button";
    983991localizedStrings["Show Path"] = "Show Path";
  • trunk/Source/WebInspectorUI/UserInterface/Base/Setting.js

    r248201 r248202  
    184184    experimentalEnableNewTabBar: new WI.Setting("experimental-enable-new-tab-bar", false),
    185185    experimentalEnableSourcesTab: new WI.Setting("experimental-enable-sources-tab", false),
     186    experimentalEnableStylesIcons: new WI.Setting("experimental-styles-icons", false),
    186187    experimentalEnableStylesJumpToEffective: new WI.Setting("experimental-styles-jump-to-effective", false),
    187188
  • trunk/Source/WebInspectorUI/UserInterface/Controllers/CSSManager.js

    r246509 r248202  
    138138
    139139        switch (pseudoId) {
    140         case InspectorBackend.domains.CSS.PseudoId.FirstLine:
     140        case CSSManager.PseudoSelectorNames.FirstLine:
    141141            return WI.unlocalizedString("::first-line");
    142         case InspectorBackend.domains.CSS.PseudoId.FirstLetter:
     142        case CSSManager.PseudoSelectorNames.FirstLetter:
    143143            return WI.unlocalizedString("::first-letter");
    144         case InspectorBackend.domains.CSS.PseudoId.Marker:
     144        case CSSManager.PseudoSelectorNames.Marker:
    145145            return WI.unlocalizedString("::marker");
    146         case InspectorBackend.domains.CSS.PseudoId.Before:
     146        case CSSManager.PseudoSelectorNames.Before:
    147147            return WI.unlocalizedString("::before");
    148         case InspectorBackend.domains.CSS.PseudoId.After:
     148        case CSSManager.PseudoSelectorNames.After:
    149149            return WI.unlocalizedString("::after");
    150         case InspectorBackend.domains.CSS.PseudoId.Selection:
     150        case CSSManager.PseudoSelectorNames.Selection:
    151151            return WI.unlocalizedString("::selection");
    152         case InspectorBackend.domains.CSS.PseudoId.Scrollbar:
     152        case CSSManager.PseudoSelectorNames.Scrollbar:
    153153            return WI.unlocalizedString("::scrollbar");
    154         case InspectorBackend.domains.CSS.PseudoId.ScrollbarThumb:
     154        case CSSManager.PseudoSelectorNames.ScrollbarThumb:
    155155            return WI.unlocalizedString("::scrollbar-thumb");
    156         case InspectorBackend.domains.CSS.PseudoId.ScrollbarButton:
     156        case CSSManager.PseudoSelectorNames.ScrollbarButton:
    157157            return WI.unlocalizedString("::scrollbar-button");
    158         case InspectorBackend.domains.CSS.PseudoId.ScrollbarTrack:
     158        case CSSManager.PseudoSelectorNames.ScrollbarTrack:
    159159            return WI.unlocalizedString("::scrollbar-track");
    160         case InspectorBackend.domains.CSS.PseudoId.ScrollbarTrackPiece:
     160        case CSSManager.PseudoSelectorNames.ScrollbarTrackPiece:
    161161            return WI.unlocalizedString("::scrollbar-track-piece");
    162         case InspectorBackend.domains.CSS.PseudoId.ScrollbarCorner:
     162        case CSSManager.PseudoSelectorNames.ScrollbarCorner:
    163163            return WI.unlocalizedString("::scrollbar-corner");
    164         case InspectorBackend.domains.CSS.PseudoId.Resizer:
     164        case CSSManager.PseudoSelectorNames.Resizer:
    165165            return WI.unlocalizedString("::resizer");
    166166
     
    741741};
    742742
     743WI.CSSManager.PseudoSelectorNames = {
     744    After: "after",
     745    Before: "before",
     746    FirstLetter: "first-letter",
     747    FirstLine: "first-line",
     748    Marker: "marker",
     749    Resizer: "resizer",
     750    Scrollbar: "scrollbar",
     751    ScrollbarButton: "scrollbar-button",
     752    ScrollbarCorner: "scrollbar-corner",
     753    ScrollbarThumb: "scrollbar-thumb",
     754    ScrollbarTrack: "scrollbar-track",
     755    ScrollbarTrackPiece: "scrollbar-track-piece",
     756    Selection: "selection",
     757};
     758
    743759WI.CSSManager.PseudoElementNames = ["before", "after"];
    744760WI.CSSManager.ForceablePseudoClasses = ["active", "focus", "hover", "visited"];
  • trunk/Source/WebInspectorUI/UserInterface/Main.html

    r247252 r248202  
    207207    <link rel="stylesheet" href="Views/StorageIcons.css">
    208208    <link rel="stylesheet" href="Views/StorageSidebarPanel.css">
     209    <link rel="stylesheet" href="Views/StyleRuleIcons.css">
    209210    <link rel="stylesheet" href="Views/SyntaxHighlightingDefaultTheme.css">
    210211    <link rel="stylesheet" href="Views/TabBar.css">
  • trunk/Source/WebInspectorUI/UserInterface/Models/CSSSelector.js

    r236766 r248202  
    4141    get dynamic() { return this._dynamic; }
    4242
    43     isPseudoElementSelector()
     43    isPseudoSelector()
    4444    {
    45         return WI.CSSManager.PseudoElementNames.some((name) => this._text.includes(`:${name}`));
     45        return Object.values(WI.CSSManager.PseudoSelectorNames).some((pseudoId) => (new RegExp("(?:\\b|^):{1,2}(?:-webkit-)?" + pseudoId + "(?:\\b|$)")).test(this._text));
    4646    }
    4747};
  • trunk/Source/WebInspectorUI/UserInterface/Models/CSSStyleDeclaration.js

    r246621 r248202  
    452452    }
    453453
     454    generateCSSRuleString()
     455    {
     456        let indentString = WI.indentString();
     457        let styleText = "";
     458        let mediaList = this.mediaList.filter((media) => media.text !== "all");
     459        let mediaQueriesCount = mediaList.length;
     460        for (let i = mediaQueriesCount - 1; i >= 0; --i)
     461            styleText += indentString.repeat(mediaQueriesCount - i - 1) + "@media " + mediaList[i].text + " {\n";
     462
     463        styleText += indentString.repeat(mediaQueriesCount) + this.selectorText + " {\n";
     464
     465        for (let property of (this._styleSheetTextRange ? this.visibleProperties : this._properties))
     466            styleText += indentString.repeat(mediaQueriesCount + 1) + property.formattedText + "\n";
     467
     468        for (let i = mediaQueriesCount; i > 0; --i)
     469            styleText += indentString.repeat(i) + "}\n";
     470
     471        styleText += "}";
     472
     473        return styleText;
     474    }
     475
    454476    // Protected
    455477
  • trunk/Source/WebInspectorUI/UserInterface/Views/SettingsTabContentView.js

    r247043 r248202  
    308308        experimentalSettingsView.addSeparator();
    309309
    310         experimentalSettingsView.addSetting(WI.UIString("Styles:"), WI.settings.experimentalEnableStylesJumpToEffective, WI.UIString("Show Jump to Effective Property Button"));
    311         experimentalSettingsView.addSeparator();
     310        if (InspectorBackend.domains.CSS) {
     311            let stylesGroup = experimentalSettingsView.addGroup(WI.UIString("Styles:"));
     312            stylesGroup.addSetting(WI.settings.experimentalEnableStylesIcons, WI.UIString("Show Icons"));
     313            stylesGroup.addSetting(WI.settings.experimentalEnableStylesJumpToEffective, WI.UIString("Show Jump to Effective Property Button"));
     314            experimentalSettingsView.addSeparator();
     315        }
    312316
    313317        let reloadInspectorButton = document.createElement("button");
     
    338342        listenForChange(WI.settings.experimentalEnableLayersTab);
    339343        listenForChange(WI.settings.experimentalEnableNewTabBar);
    340         listenForChange(WI.settings.experimentalEnableStylesJumpToEffective);
     344
     345        if (InspectorBackend.domains.CSS) {
     346            listenForChange(WI.settings.experimentalEnableStylesIcons);
     347            listenForChange(WI.settings.experimentalEnableStylesJumpToEffective);
     348        }
    341349
    342350        this.addSettingsView(experimentalSettingsView);
  • trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.css

    r244951 r248202  
    3636}
    3737
     38.spreadsheet-style-declaration-editor:empty {
     39    height: 2px;
     40}
     41
    3842.spreadsheet-style-declaration-editor .property {
    3943    padding-right: var(--css-declaration-horizontal-padding);
     
    6872    z-index: 1;
    6973    max-width: 100%;
    70 }
    71 
    72 .spreadsheet-style-declaration-editor.no-properties {
    73     display: none;
    7474}
    7575
  • trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.js

    r247760 r248202  
    8989
    9090        let properties = this.propertiesToRender;
    91         this.element.classList.toggle("no-properties", !properties.length);
    9291
    9392        // FIXME: Only re-layout properties that have been modified and preserve focus whenever possible.
  • trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationSection.css

    r241980 r248202  
    4646.spreadsheet-css-declaration :matches(.header, .header-media):first-child {
    4747    padding-top: var(--css-declaration-vertical-padding);
     48}
     49
     50.spreadsheet-css-declaration .header.editing-selector .selector {
     51    margin-top: 1px;
    4852}
    4953
     
    100104}
    101105
     106.spreadsheet-css-declaration .selector > .icon {
     107    width: 16px;
     108    height: 16px;
     109    margin-top: -1px;
     110    -webkit-margin-start: -2px;
     111    vertical-align: -3.5px;
     112    -webkit-user-select: none;
     113}
     114
     115.spreadsheet-css-declaration .selector > .icon + * {
     116    -webkit-padding-start: 2px;
     117}
     118
    102119.spreadsheet-css-declaration .selector > span {
    103120    color: var(--text-color-secondary);
     121}
     122
     123.spreadsheet-css-declaration .selector.style-attribute > span {
     124    -webkit-margin-start: 0.5px;
    104125}
    105126
  • trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationSection.js

    r247760 r248202  
    6363        super.initialLayout();
    6464
     65        if (WI.settings.experimentalEnableStylesIcons.value) {
     66            let iconClassName = null;
     67            switch (this._style.type) {
     68            case WI.CSSStyleDeclaration.Type.Rule:
     69                console.assert(this._style.ownerRule);
     70                if (this._style.inherited) {
     71                    iconClassName = "inherited-style-rule-icon";
     72                    break;
     73                }
     74
     75                switch (this._style.ownerRule.type) {
     76                case WI.CSSStyleSheet.Type.Author:
     77                    iconClassName = "author-style-rule-icon";
     78                    break;
     79                case WI.CSSStyleSheet.Type.User:
     80                    iconClassName = "user-style-rule-icon";
     81                    break;
     82                case WI.CSSStyleSheet.Type.UserAgent:
     83                    iconClassName = "user-agent-style-rule-icon";
     84                    break;
     85                case WI.CSSStyleSheet.Type.Inspector:
     86                    iconClassName = "inspector-style-rule-icon";
     87                    break;
     88                }
     89                break;
     90            case WI.CSSStyleDeclaration.Type.Inline:
     91            case WI.CSSStyleDeclaration.Type.Attribute:
     92                if (this._style.inherited)
     93                    iconClassName = "inherited-element-style-rule-icon";
     94                else
     95                    iconClassName = WI.DOMTreeElementPathComponent.DOMElementIconStyleClassName;
     96                break;
     97            }
     98            console.assert(iconClassName);
     99            this._element.classList.add(iconClassName);
     100        }
     101
    65102        this._headerElement = document.createElement("div");
    66103        this._headerElement.classList.add("header");
     
    298335        };
    299336
     337        if (WI.settings.experimentalEnableStylesIcons.value) {
     338            if (!this._iconElement) {
     339                this._iconElement = document.createElement("img");
     340                this._iconElement.classList.add("icon");
     341                WI.addMouseDownContextMenuHandlers(this._iconElement, this._populateIconElementContextMenu.bind(this));
     342            }
     343            this._selectorElement.appendChild(this._iconElement);
     344        }
     345
    300346        switch (this._style.type) {
    301347        case WI.CSSStyleDeclaration.Type.Rule:
    302348            console.assert(this._style.ownerRule);
    303349
     350            var hasMatchingPseudoSelector = false;
     351
    304352            var selectors = this._style.ownerRule.selectors;
    305             var matchedSelectorIndices = this._style.ownerRule.matchedSelectorIndices;
    306353            if (selectors.length) {
    307354                for (let i = 0; i < selectors.length; ++i) {
    308                     appendSelector(selectors[i], matchedSelectorIndices.includes(i));
     355                    let matched = this._style.ownerRule.matchedSelectorIndices.includes(i);
     356                    if (matched && selectors[i].isPseudoSelector())
     357                        hasMatchingPseudoSelector = true;
     358
     359                    appendSelector(selectors[i], matched);
    309360                    if (i < selectors.length - 1)
    310361                        this._selectorElement.append(", ");
     
    313364                appendSelectorTextKnownToMatch(this._style.ownerRule.selectorText);
    314365
     366            this._element.classList.toggle("pseudo-selector", hasMatchingPseudoSelector);
    315367            break;
    316368
    317         case WI.CSSStyleDeclaration.Type.Inline:
    318             this._selectorElement.textContent = WI.UIString("Style Attribute", "CSS properties defined via HTML style attribute");
     369        case WI.CSSStyleDeclaration.Type.Inline: {
    319370            this._selectorElement.classList.add("style-attribute");
     371            let wrapper = this._selectorElement.appendChild(document.createElement("span"));
     372            wrapper.textContent = WI.UIString("Style Attribute", "CSS properties defined via HTML style attribute");
    320373            break;
     374        }
    321375
    322376        case WI.CSSStyleDeclaration.Type.Attribute:
     
    431485    }
    432486
     487    _populateIconElementContextMenu(contextMenu)
     488    {
     489        contextMenu.appendItem(WI.UIString("Copy Rule"), () => {
     490            InspectorFrontendHost.copyText(this._style.generateCSSRuleString());
     491        });
     492
     493        if (this._style.editable && this._style.properties.length) {
     494            let shouldDisable = this._style.properties.some((property) => property.enabled);
     495            contextMenu.appendItem(shouldDisable ? WI.UIString("Disable Rule") : WI.UIString("Enable Rule"), () => {
     496                for (let property of this._style.properties)
     497                    property.commentOut(shouldDisable);
     498            });
     499        }
     500
     501        if (!this._style.inherited) {
     502            let generateSelector = () => {
     503                if (this._style.type === WI.CSSStyleDeclaration.Type.Attribute)
     504                    return this._style.node.displayName;
     505                return this._style.selectorText;
     506            };
     507
     508            let createNewRule = (selector, text) => {
     509                if (this._delegate && this._delegate.spreadsheetCSSStyleDeclarationSectionAddNewRule)
     510                    this._delegate.spreadsheetCSSStyleDeclarationSectionAddNewRule(this, selector, text);
     511                else
     512                    this._style.nodeStyles.addRule(selector, text);
     513            };
     514
     515            contextMenu.appendSeparator();
     516
     517            contextMenu.appendItem(WI.UIString("Duplicate Selector"), () => {
     518                createNewRule(generateSelector());
     519            });
     520
     521            if (!WI.CSSManager.PseudoElementNames.some((className) => this._style.selectorText.includes(":" + className))) {
     522                let addPseudoRule = (pseudoSelector, text) => {
     523                    let selector = null;
     524                    if (this._style.ownerRule)
     525                        selector = this._style.ownerRule.selectors.map((selector) => selector.text + pseudoSelector).join(", ");
     526                    else
     527                        selector = generateSelector() + pseudoSelector;
     528                    createNewRule(selector, text);
     529                };
     530
     531                if (WI.CSSManager.ForceablePseudoClasses.every((className) => !this._style.selectorText.includes(":" + className))) {
     532                    contextMenu.appendSeparator();
     533
     534                     for (let pseudoClass of WI.CSSManager.ForceablePseudoClasses) {
     535                        if (pseudoClass === "visited" && this._style.node.nodeName() !== "A")
     536                            continue;
     537
     538                        let pseudoClassSelector = ":" + pseudoClass;
     539                        contextMenu.appendItem(WI.UIString("Add %s Rule").format(pseudoClassSelector), () => {
     540                            this._style.node.setPseudoClassEnabled(pseudoClass, true);
     541                            addPseudoRule(pseudoClassSelector);
     542                        });
     543                    }
     544                }
     545
     546                if (this._style.type === WI.CSSStyleDeclaration.Type.Rule) {
     547                    contextMenu.appendSeparator();
     548
     549                    for (let pseudoElement of WI.CSSManager.PseudoElementNames) {
     550                        let pseudoElementSelector = "::" + pseudoElement;
     551                        contextMenu.appendItem(WI.UIString("Create %s Rule").format(pseudoElementSelector), () => {
     552                            addPseudoRule(pseudoElementSelector, "content: \"\";");
     553                        });
     554                    }
     555                }
     556            }
     557        }
     558
     559        if (this._style.ownerRule && this._style.ownerRule.sourceCodeLocation) {
     560            contextMenu.appendSeparator();
     561
     562            let label = null;
     563            let sourceCode = this._style.ownerRule.sourceCodeLocation.displaySourceCode;
     564            if (sourceCode instanceof WI.CSSStyleSheet || (sourceCode instanceof WI.Resource && sourceCode.type === WI.Resource.Type.Stylesheet))
     565                label = WI.UIString("Reveal in Stylesheet");
     566            else if (WI.settings.experimentalEnableSourcesTab.value)
     567                label = WI.UIString("Reveal in Sources Tab");
     568            else
     569                label = WI.UIString("Reveal in Resources Tab");
     570
     571            contextMenu.appendItem(label, () => {
     572                WI.showSourceCodeLocation(this._style.ownerRule.sourceCodeLocation, {
     573                    ignoreNetworkTab: true,
     574                    ignoreSearchTab: true,
     575                });
     576            });
     577        }
     578    }
     579
    433580    _handleWindowClick(event)
    434581    {
  • trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetRulesStyleDetailsPanel.js

    r246952 r248202  
    206206    }
    207207
     208    spreadsheetCSSStyleDeclarationSectionAddNewRule(section, selector, text)
     209    {
     210        this._newRuleSelector = selector;
     211        this.nodeStyles.addRule(this._newRuleSelector, text);
     212    }
     213
    208214    // Protected
    209215
     
    301307        let afterPseudoId = null;
    302308        if (InspectorBackend.domains.CSS.PseudoId) {
    303             beforePseudoId = InspectorBackend.domains.CSS.PseudoId.Before;
    304             afterPseudoId = InspectorBackend.domains.CSS.PseudoId.After;
     309            beforePseudoId = WI.CSSManager.PseudoSelectorNames.Before;
     310            afterPseudoId = WI.CSSManager.PseudoSelectorNames.After;
    305311        } else {
    306312            // Compatibility (iOS 12.2): CSS.PseudoId did not exist.
  • trunk/Source/WebInspectorUI/UserInterface/Views/StyleRuleIcons.css

    r248201 r248202  
    11/*
    2  * Copyright (C) 2014 Apple Inc. All rights reserved.
     2 * Copyright (C) 2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2424 */
    2525
    26 WI.CSSSelector = class CSSSelector
    27 {
    28     constructor(text, specificity, dynamic)
    29     {
    30         console.assert(text);
     26.author-style-rule-icon .icon {
     27    content: url(../Images/StyleRule.svg#author);
     28}
    3129
    32         this._text = text;
    33         this._specificity = specificity || null;
    34         this._dynamic = dynamic || false;
    35     }
     30.author-style-rule-icon.pseudo-selector .icon {
     31    content: url(../Images/StyleRulePseudo.svg#author);
     32}
    3633
    37     // Public
     34.user-style-rule-icon .icon {
     35    content: url(../Images/StyleRule.svg#user);
     36}
    3837
    39     get text() { return this._text; }
    40     get specificity() { return this._specificity; }
    41     get dynamic() { return this._dynamic; }
     38.user-style-rule-icon.pseudo-selector .icon {
     39    content: url(../Images/StyleRulePseudo.svg#user);
     40}
    4241
    43     isPseudoElementSelector()
    44     {
    45         return WI.CSSManager.PseudoElementNames.some((name) => this._text.includes(`:${name}`));
    46     }
    47 };
     42.user-agent-style-rule-icon .icon {
     43    content: url(../Images/StyleRule.svg#useragent);
     44}
     45
     46.user-agent-style-rule-icon.pseudo-selector .icon {
     47    content: url(../Images/StyleRulePseudo.svg#useragent);
     48}
     49
     50.inspector-style-rule-icon .icon {
     51    content: url(../Images/StyleRule.svg#inspector);
     52}
     53
     54.inspector-style-rule-icon.pseudo-selector .icon {
     55    content: url(../Images/StyleRulePseudo.svg#inspector);
     56}
     57
     58.inherited-style-rule-icon .icon {
     59    content: url(../Images/StyleRule.svg#inherited);
     60}
     61
     62.inherited-element-style-rule-icon .icon {
     63    content: url(../Images/StyleRuleInheritedElement.svg);
     64}
Note: See TracChangeset for help on using the changeset viewer.