Title: [237659] trunk/Source/WebInspectorUI
Revision
237659
Author
nvasil...@apple.com
Date
2018-10-31 15:52:11 -0700 (Wed, 31 Oct 2018)

Log Message

Web Inspector: Styles: implement copying and deletion of multiple properties
https://bugs.webkit.org/show_bug.cgi?id=191037
<rdar://problem/45650078>

Reviewed by Brian Burg.

This patch should only work with "Enable Selection of Multiple Properties" checked. It shouldn't introduce any
changes when this setting is unchecked.

Mousedown on a property (1) and moving the mouse cursor to another property (2) should select properties 1, 2, and
all properties between them until mouseup is fired.

Once selected:
- Pressing Command-C should copy the selected properties.
- Pressing Delete should remove the properties.

* UserInterface/Models/CSSProperty.js:
(WI.CSSProperty.prototype.get formattedText):
* UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.css:
(.spreadsheet-style-declaration-editor):
(.multiple-properties-selection .spreadsheet-style-declaration-editor .property):
(.multiple-properties-selection .spreadsheet-style-declaration-editor :matches(.name, .value):not(.editing)):
(.multiple-properties-selection .spreadsheet-style-declaration-editor .property.selected):
(.multiple-properties-selection .spreadsheet-style-declaration-editor .property.selected:focus):
(@media (prefers-dark-interface)):

* UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.js:
(WI.SpreadsheetCSSStyleDeclarationEditor):
(WI.SpreadsheetCSSStyleDeclarationEditor.prototype.initialLayout):
(WI.SpreadsheetCSSStyleDeclarationEditor.prototype.selectProperties):
(WI.SpreadsheetCSSStyleDeclarationEditor.prototype.deselectProperties):
(WI.SpreadsheetCSSStyleDeclarationEditor.prototype.spreadsheetStylePropertyBlur):
(WI.SpreadsheetCSSStyleDeclarationEditor.prototype.spreadsheetStylePropertyMouseEnter):
(WI.SpreadsheetCSSStyleDeclarationEditor.prototype.spreadsheetStylePropertyMouseLeave):
(WI.SpreadsheetCSSStyleDeclarationEditor.prototype.spreadsheetStylePropertyCopy):
(WI.SpreadsheetCSSStyleDeclarationEditor.prototype._handleKeyDown):
(WI.SpreadsheetCSSStyleDeclarationEditor.prototype._hasSelectedProperties):
Property selection is defined as two numbers: anchorIndex and focusIndex.
The property with focusIndex is actually focused. The focus outline is replaced by a more subtle left blue border.

* UserInterface/Views/SpreadsheetCSSStyleDeclarationSection.css:
(.spreadsheet-css-declaration.selecting,):
* UserInterface/Views/SpreadsheetCSSStyleDeclarationSection.js:
(WI.SpreadsheetCSSStyleDeclarationSection):
(WI.SpreadsheetCSSStyleDeclarationSection.prototype.spreadsheetCSSStyleDeclarationEditorPropertyBlur):
(WI.SpreadsheetCSSStyleDeclarationSection.prototype.spreadsheetCSSStyleDeclarationEditorPropertyMouseEnter):
(WI.SpreadsheetCSSStyleDeclarationSection.prototype.spreadsheetCSSStyleDeclarationEditorPropertyMouseLeave):
(WI.SpreadsheetCSSStyleDeclarationSection.prototype._handleMouseDown):
(WI.SpreadsheetCSSStyleDeclarationSection.prototype._handleWindowMouseUp):
(WI.SpreadsheetCSSStyleDeclarationSection.prototype._handleClick):
* UserInterface/Views/SpreadsheetStyleProperty.js:
(WI.SpreadsheetStyleProperty):
Implement copying the same way it's done for DataGrid: by adding copyHandler property to the focused element.
Add `tabIndex=-1` so the property element can be focused.

(WI.SpreadsheetStyleProperty.prototype.get property):
(WI.SpreadsheetStyleProperty.prototype.get selected):
(WI.SpreadsheetStyleProperty.prototype.set selected):
(WI.SpreadsheetStyleProperty.prototype.remove):
(WI.SpreadsheetStyleProperty.prototype.updateStatus):
(WI.SpreadsheetStyleProperty.prototype.handleCopyEvent):
(WI.SpreadsheetStyleProperty.prototype.spreadsheetTextFieldDidCommit):
(WI.SpreadsheetStyleProperty.prototype.spreadsheetTextFieldDidBlur):
(WI.SpreadsheetStyleProperty.prototype._handleNamePaste):

Modified Paths

Diff

Modified: trunk/Source/WebInspectorUI/ChangeLog (237658 => 237659)


--- trunk/Source/WebInspectorUI/ChangeLog	2018-10-31 22:44:27 UTC (rev 237658)
+++ trunk/Source/WebInspectorUI/ChangeLog	2018-10-31 22:52:11 UTC (rev 237659)
@@ -1,3 +1,70 @@
+2018-10-31  Nikita Vasilyev  <nvasil...@apple.com>
+
+        Web Inspector: Styles: implement copying and deletion of multiple properties
+        https://bugs.webkit.org/show_bug.cgi?id=191037
+        <rdar://problem/45650078>
+
+        Reviewed by Brian Burg.
+
+        This patch should only work with "Enable Selection of Multiple Properties" checked. It shouldn't introduce any
+        changes when this setting is unchecked.
+
+        Mousedown on a property (1) and moving the mouse cursor to another property (2) should select properties 1, 2, and
+        all properties between them until mouseup is fired.
+
+        Once selected:
+        - Pressing Command-C should copy the selected properties.
+        - Pressing Delete should remove the properties.
+
+        * UserInterface/Models/CSSProperty.js:
+        (WI.CSSProperty.prototype.get formattedText):
+        * UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.css:
+        (.spreadsheet-style-declaration-editor):
+        (.multiple-properties-selection .spreadsheet-style-declaration-editor .property):
+        (.multiple-properties-selection .spreadsheet-style-declaration-editor :matches(.name, .value):not(.editing)):
+        (.multiple-properties-selection .spreadsheet-style-declaration-editor .property.selected):
+        (.multiple-properties-selection .spreadsheet-style-declaration-editor .property.selected:focus):
+        (@media (prefers-dark-interface)):
+
+        * UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.js:
+        (WI.SpreadsheetCSSStyleDeclarationEditor):
+        (WI.SpreadsheetCSSStyleDeclarationEditor.prototype.initialLayout):
+        (WI.SpreadsheetCSSStyleDeclarationEditor.prototype.selectProperties):
+        (WI.SpreadsheetCSSStyleDeclarationEditor.prototype.deselectProperties):
+        (WI.SpreadsheetCSSStyleDeclarationEditor.prototype.spreadsheetStylePropertyBlur):
+        (WI.SpreadsheetCSSStyleDeclarationEditor.prototype.spreadsheetStylePropertyMouseEnter):
+        (WI.SpreadsheetCSSStyleDeclarationEditor.prototype.spreadsheetStylePropertyMouseLeave):
+        (WI.SpreadsheetCSSStyleDeclarationEditor.prototype.spreadsheetStylePropertyCopy):
+        (WI.SpreadsheetCSSStyleDeclarationEditor.prototype._handleKeyDown):
+        (WI.SpreadsheetCSSStyleDeclarationEditor.prototype._hasSelectedProperties):
+        Property selection is defined as two numbers: anchorIndex and focusIndex.
+        The property with focusIndex is actually focused. The focus outline is replaced by a more subtle left blue border.
+
+        * UserInterface/Views/SpreadsheetCSSStyleDeclarationSection.css:
+        (.spreadsheet-css-declaration.selecting,):
+        * UserInterface/Views/SpreadsheetCSSStyleDeclarationSection.js:
+        (WI.SpreadsheetCSSStyleDeclarationSection):
+        (WI.SpreadsheetCSSStyleDeclarationSection.prototype.spreadsheetCSSStyleDeclarationEditorPropertyBlur):
+        (WI.SpreadsheetCSSStyleDeclarationSection.prototype.spreadsheetCSSStyleDeclarationEditorPropertyMouseEnter):
+        (WI.SpreadsheetCSSStyleDeclarationSection.prototype.spreadsheetCSSStyleDeclarationEditorPropertyMouseLeave):
+        (WI.SpreadsheetCSSStyleDeclarationSection.prototype._handleMouseDown):
+        (WI.SpreadsheetCSSStyleDeclarationSection.prototype._handleWindowMouseUp):
+        (WI.SpreadsheetCSSStyleDeclarationSection.prototype._handleClick):
+        * UserInterface/Views/SpreadsheetStyleProperty.js:
+        (WI.SpreadsheetStyleProperty):
+        Implement copying the same way it's done for DataGrid: by adding copyHandler property to the focused element.
+        Add `tabIndex=-1` so the property element can be focused.
+
+        (WI.SpreadsheetStyleProperty.prototype.get property):
+        (WI.SpreadsheetStyleProperty.prototype.get selected):
+        (WI.SpreadsheetStyleProperty.prototype.set selected):
+        (WI.SpreadsheetStyleProperty.prototype.remove):
+        (WI.SpreadsheetStyleProperty.prototype.updateStatus):
+        (WI.SpreadsheetStyleProperty.prototype.handleCopyEvent):
+        (WI.SpreadsheetStyleProperty.prototype.spreadsheetTextFieldDidCommit):
+        (WI.SpreadsheetStyleProperty.prototype.spreadsheetTextFieldDidBlur):
+        (WI.SpreadsheetStyleProperty.prototype._handleNamePaste):
+
 2018-10-31  Devin Rousso  <drou...@apple.com>
 
         Web Inspector: Audit: attempt to re-link DOM nodes for imported results

Modified: trunk/Source/WebInspectorUI/UserInterface/Models/CSSProperty.js (237658 => 237659)


--- trunk/Source/WebInspectorUI/UserInterface/Models/CSSProperty.js	2018-10-31 22:44:27 UTC (rev 237658)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/CSSProperty.js	2018-10-31 22:52:11 UTC (rev 237659)
@@ -164,6 +164,14 @@
         this._text = newText;
     }
 
+    get formattedText()
+    {
+        if (!this._name)
+            return "";
+
+        return `${this._name}: ${this._rawValue};`;
+    }
+
     get name()
     {
         return this._name;

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.css (237658 => 237659)


--- trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.css	2018-10-31 22:44:27 UTC (rev 237658)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.css	2018-10-31 22:52:11 UTC (rev 237659)
@@ -30,6 +30,9 @@
     font-size: 11px;
     color: hsl(0, 0%, 70%);
     -webkit-user-select: text;
+
+    --background-color-selected: hsl(210, 98%, 93%);
+    --border-color-selected: hsl(225, 91%, 70%);
 }
 
 .spreadsheet-style-declaration-editor .property {
@@ -37,6 +40,11 @@
     padding-left: calc(var(--css-declaration-horizontal-padding) + 17px);
 }
 
+.multiple-properties-selection .spreadsheet-style-declaration-editor .property {
+    border-left: 1px solid transparent;
+    outline: none;
+}
+
 .spreadsheet-style-declaration-editor .property:not(.disabled) .name {
     color: var(--syntax-highlight-boolean-color);
 }
@@ -45,6 +53,10 @@
     color: var(--text-color);
 }
 
+.multiple-properties-selection .spreadsheet-style-declaration-editor :matches(.name, .value):not(.editing) {
+    outline: none;
+}
+
 .spreadsheet-style-declaration-editor :matches(.name, .value).editing {
     outline: 1px solid white !important;
     box-shadow: 0 1px 2px 1px hsla(0, 0%, 0%, 0.6);
@@ -124,6 +136,14 @@
     -webkit-clip-path: polygon(0% 50%, 6px 0%, 100% 0%, 100% 100%, 6px 100%);
 }
 
+.multiple-properties-selection .spreadsheet-style-declaration-editor .property.selected {
+    background-color: var(--background-color-selected);
+}
+
+.multiple-properties-selection .spreadsheet-style-declaration-editor .property.selected:focus {
+    border-left-color: var(--border-color-selected);
+}
+
 .spreadsheet-style-declaration-editor .property:matches(.implicit, .not-inherited) .content > * {
     opacity: 0.5;
 }
@@ -160,6 +180,11 @@
 }
 
 @media (prefers-dark-interface) {
+    .spreadsheet-style-declaration-editor {
+        --background-color-selected: hsl(230, 51%, 36%);
+        --border-color-selected: hsl(216, 98%, 67%);
+    }
+
     .spreadsheet-style-declaration-editor :matches(.name, .value).editing {
         outline-color: var(--background-color-secondary) !important;
     }

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.js (237658 => 237659)


--- trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.js	2018-10-31 22:44:27 UTC (rev 237658)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.js	2018-10-31 22:52:11 UTC (rev 237659)
@@ -47,6 +47,9 @@
         this._propertyPendingStartEditing = null;
         this._pendingAddBlankPropertyIndexOffset = NaN;
         this._filterText = null;
+
+        this._anchorIndex = NaN;
+        this._focusIndex = NaN;
     }
 
     // Public
@@ -64,6 +67,9 @@
 
             this.focused = false;
         }, true);
+
+        if (WI.settings.experimentalEnableMultiplePropertiesSelection.value)
+            this.element.addEventListener("keydown", this._handleKeyDown.bind(this));
     }
 
     layout()
@@ -307,6 +313,43 @@
         this.needsLayout();
     }
 
+    selectProperties(anchorIndex, focusIndex)
+    {
+        console.assert(anchorIndex < this._propertyViews.length, `anchorIndex (${anchorIndex}) is greater than the last property index (${this._propertyViews.length})`);
+        console.assert(focusIndex < this._propertyViews.length, `focusIndex (${focusIndex}) is greater than the last property index (${this._propertyViews.length})`);
+
+        if (isNaN(anchorIndex) || isNaN(focusIndex)) {
+            console.error(`Nothing to select. anchorIndex (${anchorIndex}) and focusIndex (${focusIndex}) must be numbers.`);
+            this.deselectProperties();
+            return;
+        }
+
+        this._anchorIndex = anchorIndex;
+        this._focusIndex = focusIndex;
+
+        let startIndex = Math.min(anchorIndex, focusIndex);
+        let endIndex = Math.max(anchorIndex, focusIndex);
+
+        for (let i = 0; i < this._propertyViews.length; ++i) {
+            let propertyView = this._propertyViews[i];
+            let isSelected = i >= startIndex && i <= endIndex;
+            propertyView.selected = isSelected;
+        }
+
+        let property = this._propertyViews[focusIndex];
+        property.element.focus();
+    }
+
+    deselectProperties()
+    {
+        for (let propertyView  of this._propertyViews)
+            propertyView.selected = false;
+
+        this._focused = false;
+        this._anchorIndex = NaN;
+        this._focusIndex = NaN;
+    }
+
     applyFilter(filterText)
     {
         this._filterText = filterText;
@@ -330,6 +373,24 @@
 
     // SpreadsheetStyleProperty delegate
 
+    spreadsheetStylePropertyBlur(event, property)
+    {
+        if (this._suppressBlur)
+            return;
+
+        this._delegate.spreadsheetCSSStyleDeclarationEditorPropertyBlur(event, property);
+    }
+
+    spreadsheetStylePropertyMouseEnter(event, property)
+    {
+        this._delegate.spreadsheetCSSStyleDeclarationEditorPropertyMouseEnter(event, property);
+    }
+
+    spreadsheetStylePropertyMouseLeave(event, property)
+    {
+        this._delegate.spreadsheetCSSStyleDeclarationEditorPropertyMouseLeave(event, property);
+    }
+
     spreadsheetStylePropertyFocusMoved(propertyView, {direction, willRemoveProperty})
     {
         this._updatePropertiesStatus();
@@ -384,6 +445,23 @@
         this._pendingAddBlankPropertyIndexOffset = this._propertyViews.length - index;
     }
 
+    spreadsheetStylePropertyCopy(event)
+    {
+        if (!this._hasSelectedProperties())
+            return;
+
+        let formattedProperties = [];
+        let startIndex = Math.min(this._anchorIndex, this._focusIndex);
+        let endIndex = Math.max(this._anchorIndex, this._focusIndex);
+        for (let i = startIndex; i <= endIndex; ++i) {
+            let propertyView = this._propertyViews[i];
+            formattedProperties.push(propertyView.property.formattedText);
+        }
+
+        event.clipboardData.setData("text/plain", formattedProperties.join("\n"));
+        event.stop();
+    }
+
     spreadsheetStylePropertyRemoved(propertyView)
     {
         this._propertyViews.remove(propertyView);
@@ -412,6 +490,53 @@
 
     // Private
 
+    _handleKeyDown(event)
+    {
+        if (event.key === "ArrowUp" || event.key === "ArrowDown") {
+            let delta = event.key === "ArrowUp" ? -1 : 1;
+            let focusIndex = Number.constrain(this._focusIndex + delta, 0, this._propertyViews.length - 1);
+
+            // Blur event deselects all properties.
+            this._suppressBlur = true;
+            this.selectProperties(focusIndex, focusIndex);
+            this._suppressBlur = false;
+
+            event.stop();
+        } else if (event.key === "Backspace") {
+            if (!this._hasSelectedProperties())
+                return;
+
+            let startIndex = Math.min(this._anchorIndex, this._focusIndex);
+            let endIndex = Math.max(this._anchorIndex, this._focusIndex);
+
+            let propertyIndexToSelect = NaN;
+            if (endIndex + 1 !== this._propertyViews.length)
+                propertyIndexToSelect = startIndex;
+            else if (startIndex > 0)
+                propertyIndexToSelect = startIndex - 1;
+
+            this.deselectProperties();
+
+            for (let i = endIndex; i >= startIndex; i--)
+                this._propertyViews[i].remove();
+
+            if (!isNaN(propertyIndexToSelect)) {
+                this._suppressBlur = true;
+                this.selectProperties(propertyIndexToSelect, propertyIndexToSelect);
+                this._suppressBlur = false;
+            }
+
+            event.stop();
+
+        } else if (event.key === "Esc")
+            this.deselectProperties();
+    }
+
+    _hasSelectedProperties()
+    {
+        return !isNaN(this._anchorIndex) && !isNaN(this._focusIndex);
+    }
+
     _editablePropertyAfter(propertyIndex)
     {
         for (let index = propertyIndex + 1; index < this._propertyViews.length; index++) {

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationSection.css (237658 => 237659)


--- trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationSection.css	2018-10-31 22:44:27 UTC (rev 237658)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationSection.css	2018-10-31 22:52:11 UTC (rev 237659)
@@ -34,6 +34,11 @@
     -webkit-user-select: text;
 }
 
+.spreadsheet-css-declaration.selecting,
+.spreadsheet-css-declaration.selecting .spreadsheet-style-declaration-editor {
+    -webkit-user-select: none;
+}
+
 .spreadsheet-css-declaration :matches(.header, .header-media) {
     padding: 0 var(--css-declaration-horizontal-padding);
 }

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationSection.js (237658 => 237659)


--- trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationSection.js	2018-10-31 22:44:27 UTC (rev 237658)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationSection.js	2018-10-31 22:52:11 UTC (rev 237659)
@@ -37,6 +37,9 @@
 
         super(element);
 
+        if (WI.settings.experimentalEnableMultiplePropertiesSelection.value)
+            element.classList.add("multiple-properties-selection");
+
         this._delegate = delegate || null;
         this._style = style;
         this._propertiesEditor = null;
@@ -45,6 +48,10 @@
         this._filterText = null;
         this._shouldFocusSelectorElement = false;
         this._wasEditing = false;
+
+        this._isMousePressed = true;
+        this._mouseDownIndex = NaN;
+        this._startedSelection = false;
     }
 
     // Public
@@ -208,6 +215,26 @@
             this._delegate.spreadsheetCSSStyleDeclarationSectionStartEditingAdjacentRule(this, delta);
     }
 
+    spreadsheetCSSStyleDeclarationEditorPropertyBlur(event, property)
+    {
+        if (!this._startedSelection)
+            this._propertiesEditor.deselectProperties();
+    }
+
+    spreadsheetCSSStyleDeclarationEditorPropertyMouseEnter(event, property)
+    {
+        if (this._isMousePressed && this._startedSelection) {
+            let index = parseInt(property.element.dataset.propertyIndex);
+            this._propertiesEditor.selectProperties(this._mouseDownIndex, index);
+        }
+    }
+
+    spreadsheetCSSStyleDeclarationEditorPropertyMouseLeave(event, property)
+    {
+        if (this._isMousePressed)
+            this._startedSelection = true;
+    }
+
     applyFilter(filterText)
     {
         this._filterText = filterText;
@@ -435,11 +462,50 @@
     _handleMouseDown(event)
     {
         this._wasEditing = this._propertiesEditor.editing || document.activeElement === this._selectorElement;
+
+        if (!WI.settings.experimentalEnableMultiplePropertiesSelection.value)
+            return;
+
+        let propertyElement = event.target.closest(".property");
+        if (!propertyElement)
+            return;
+
+        this._isMousePressed = true;
+        this._startedSelection = false;
+
+        // Disable text selection on mousemove.
+        event.preventDefault();
+
+        // Canceling mousedown event prevents blur event from firing on the previously focused element.
+        if (this._wasEditing && document.activeElement)
+            document.activeElement.blur();
+
+        window.addEventListener("mouseup", this._handleWindowMouseUp.bind(this), {capture: true, once: true});
+
+        let propertyIndex = parseInt(propertyElement.dataset.propertyIndex);
+        this._propertiesEditor.deselectProperties();
+        this._mouseDownIndex = propertyIndex;
+
+        this._element.classList.add("selecting");
     }
 
+    _handleWindowMouseUp(event)
+    {
+        if (this._startedSelection) {
+            // Don't start editing name/value if there's selection.
+            event.stop();
+            this._startedSelection = false;
+        }
+
+        this._isMousePressed = false;
+        this._mouseDownIndex = NaN;
+
+        this._element.classList.remove("selecting");
+    }
+
     _handleClick(event)
     {
-        if (this._wasEditing)
+        if (this._wasEditing || this._startedSelection)
             return;
 
         if (window.getSelection().type === "Range")

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetStyleProperty.js (237658 => 237659)


--- trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetStyleProperty.js	2018-10-31 22:44:27 UTC (rev 237658)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetStyleProperty.js	2018-10-31 22:52:11 UTC (rev 237659)
@@ -44,16 +44,36 @@
 
         this._property.__propertyView = this;
 
+        this._selected = false;
         this._hasInvalidVariableValue = false;
 
         this._update();
         property.addEventListener(WI.CSSProperty.Event.OverriddenStatusChanged, this.updateStatus, this);
         property.addEventListener(WI.CSSProperty.Event.Changed, this.updateStatus, this);
+
+        if (WI.settings.experimentalEnableMultiplePropertiesSelection.value && this._property.editable) {
+            this._element.tabIndex = -1;
+
+            this._element.addEventListener("blur", (event) => {
+                this._delegate.spreadsheetStylePropertyBlur(event, this);
+            });
+
+            this._element.addEventListener("mouseenter", (event) => {
+                this._delegate.spreadsheetStylePropertyMouseEnter(event, this);
+            });
+
+            this._element.addEventListener("mouseleave", (event) => {
+                this._delegate.spreadsheetStylePropertyMouseLeave(event, this);
+            });
+
+            this._element.copyHandler = this;
+        }
     }
 
     // Public
 
     get element() { return this._element; }
+    get property() { return this._property; }
     get nameTextField() { return this._nameTextField; }
     get valueTextField() { return this._valueTextField; }
     get enabled() { return this._property.enabled; }
@@ -63,6 +83,20 @@
         this._element.dataset.propertyIndex = index;
     }
 
+    get selected()
+    {
+        return this._selected;
+    }
+
+    set selected(value)
+    {
+        if (value === this._selected)
+            return;
+
+        this._selected = value;
+        this.updateStatus();
+    }
+
     detached()
     {
         this._property.__propertyView = null;
@@ -87,6 +121,21 @@
         this._element.classList.add("highlighted");
     }
 
+    remove(replacement = null)
+    {
+        this.element.remove();
+
+        if (replacement)
+            this._property.replaceWithText(replacement);
+        else
+            this._property.remove();
+
+        this.detached();
+
+        if (this._delegate && typeof this._delegate.spreadsheetStylePropertyRemoved === "function")
+            this._delegate.spreadsheetStylePropertyRemoved(this);
+    }
+
     updateStatus()
     {
         let duplicatePropertyExistsBelow = (cssProperty) => {
@@ -140,6 +189,9 @@
         if (!this._property.enabled)
             classNames.push("disabled");
 
+        if (this._selected)
+            classNames.push("selected");
+
         this._element.className = classNames.join(" ");
         this._element.title = elementTitle;
     }
@@ -157,23 +209,13 @@
         return matches;
     }
 
-    // Private
-
-    _remove(replacement = "")
+    handleCopyEvent(event)
     {
-        this.element.remove();
+        this._delegate.spreadsheetStylePropertyCopy(event, this);
+    }
 
-        if (replacement)
-            this._property.replaceWithText(replacement);
-        else
-            this._property.remove();
+    // Private
 
-        this.detached();
-
-        if (this._delegate && typeof this._delegate.spreadsheetStylePropertyRemoved === "function")
-            this._delegate.spreadsheetStylePropertyRemoved(this);
-    }
-
     _update()
     {
         this.element.removeChildren();
@@ -315,7 +357,7 @@
         }
 
         if (willRemoveProperty)
-            this._remove();
+            this.remove();
     }
 
     spreadsheetTextFieldDidBlur(textField, event)
@@ -322,7 +364,7 @@
     {
         let focusedOutsideThisProperty = event.relatedTarget !== this._nameElement && event.relatedTarget !== this._valueElement;
         if (focusedOutsideThisProperty && (!this._nameTextField.value.trim() || !this._valueTextField.value.trim())) {
-            this._remove();
+            this.remove();
             return;
         }
 
@@ -617,7 +659,7 @@
 
         event.preventDefault();
 
-        this._remove(text);
+        this.remove(text);
 
         if (this._delegate.spreadsheetStylePropertyAddBlankPropertySoon) {
             this._delegate.spreadsheetStylePropertyAddBlankPropertySoon(this, {
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to