Title: [238599] trunk/Source/WebInspectorUI
Revision
238599
Author
[email protected]
Date
2018-11-27 18:55:42 -0800 (Tue, 27 Nov 2018)

Log Message

Web Inspector: TreeOutline should re-use multiple-selection logic from Table
https://bugs.webkit.org/show_bug.cgi?id=191483
<rdar://problem/45953305>

Reviewed by Devin Rousso.

Update TreeOutline to use SelectionController. Adopting SelectionController
in TreeOutline is not as straightforward as it was in Table. Selected items
are tracked by index, and TreeElement lacks an explicit index. As a consequence
TreeElement indexes are calcualted as needed and cached. The cache is cleared
whenever an element is added or removed.

* UserInterface/Controllers/SelectionController.js:
(WI.SelectionController.prototype.didInsertItem):
(WI.SelectionController.prototype.didRemoveItem):
(WI.SelectionController.prototype.handleKeyDown):
Drive-by syntax error fix.
(WI.SelectionController.prototype._adjustIndexesAfter):
(WI.SelectionController):

* UserInterface/Views/DOMTreeElement.js:
(WI.DOMTreeElement.prototype.canSelectOnMouseDown):
(WI.DOMTreeElement.prototype.selectOnMouseDown): Deleted.

* UserInterface/Views/DOMTreeOutline.js:
(WI.DOMTreeOutline.prototype._onmousedown):
Item selection is now handled by SelectionController.

* UserInterface/Views/ShaderProgramTreeElement.js:
(WI.ShaderProgramTreeElement.prototype.canSelectOnMouseDown):
(WI.ShaderProgramTreeElement.prototype.selectOnMouseDown): Deleted.

* UserInterface/Views/TreeElement.js:
(WI.TreeElement.prototype.canSelectOnMouseDown):
(WI.TreeElement.prototype._attach):
(WI.TreeElement.prototype.select):
(WI.TreeElement.prototype.deselect):
Route item selection through the parent TreeOutline, in order to go though
the TreeOutline's SelectionController.

(WI.TreeElement.treeElementMouseDown): Deleted.
Moved handler to TreeOutline, which owns the SelectionController that
needs to respond to mouse events.

* UserInterface/Views/TreeOutline.js:
(WI.TreeOutline):
(WI.TreeOutline.prototype.get allowsMultipleSelection):
(WI.TreeOutline.prototype.set allowsMultipleSelection):
(WI.TreeOutline.prototype.get selectedTreeElement):
(WI.TreeOutline.prototype.set selectedTreeElement):
(WI.TreeOutline.prototype.insertChild):
(WI.TreeOutline.prototype.removeChildAtIndex):
(WI.TreeOutline.prototype._rememberTreeElement):
(WI.TreeOutline.prototype._forgetTreeElement):
(WI.TreeOutline.prototype._treeKeyDown):
(WI.TreeOutline.prototype.selectionControllerNumberOfItems):
(WI.TreeOutline.prototype.selectionControllerSelectionDidChange):
(WI.TreeOutline.prototype.selectionControllerNextSelectableIndex):
(WI.TreeOutline.prototype.selectionControllerPreviousSelectableIndex):
(WI.TreeOutline.prototype.selectTreeElementInternal):
(WI.TreeOutline._generateStyleRulesIfNeeded._indexOfTreeElement.previousElement):
(WI.TreeOutline._generateStyleRulesIfNeeded):

Modified Paths

Diff

Modified: trunk/Source/WebInspectorUI/ChangeLog (238598 => 238599)


--- trunk/Source/WebInspectorUI/ChangeLog	2018-11-28 02:16:25 UTC (rev 238598)
+++ trunk/Source/WebInspectorUI/ChangeLog	2018-11-28 02:55:42 UTC (rev 238599)
@@ -1,3 +1,68 @@
+2018-11-27  Matt Baker  <[email protected]>
+
+        Web Inspector: TreeOutline should re-use multiple-selection logic from Table
+        https://bugs.webkit.org/show_bug.cgi?id=191483
+        <rdar://problem/45953305>
+
+        Reviewed by Devin Rousso.
+
+        Update TreeOutline to use SelectionController. Adopting SelectionController
+        in TreeOutline is not as straightforward as it was in Table. Selected items
+        are tracked by index, and TreeElement lacks an explicit index. As a consequence
+        TreeElement indexes are calcualted as needed and cached. The cache is cleared
+        whenever an element is added or removed.
+
+        * UserInterface/Controllers/SelectionController.js:
+        (WI.SelectionController.prototype.didInsertItem):
+        (WI.SelectionController.prototype.didRemoveItem):
+        (WI.SelectionController.prototype.handleKeyDown):
+        Drive-by syntax error fix.
+        (WI.SelectionController.prototype._adjustIndexesAfter):
+        (WI.SelectionController):
+
+        * UserInterface/Views/DOMTreeElement.js:
+        (WI.DOMTreeElement.prototype.canSelectOnMouseDown):
+        (WI.DOMTreeElement.prototype.selectOnMouseDown): Deleted.
+
+        * UserInterface/Views/DOMTreeOutline.js:
+        (WI.DOMTreeOutline.prototype._onmousedown):
+        Item selection is now handled by SelectionController.
+
+        * UserInterface/Views/ShaderProgramTreeElement.js:
+        (WI.ShaderProgramTreeElement.prototype.canSelectOnMouseDown):
+        (WI.ShaderProgramTreeElement.prototype.selectOnMouseDown): Deleted.
+
+        * UserInterface/Views/TreeElement.js:
+        (WI.TreeElement.prototype.canSelectOnMouseDown):
+        (WI.TreeElement.prototype._attach):
+        (WI.TreeElement.prototype.select):
+        (WI.TreeElement.prototype.deselect):
+        Route item selection through the parent TreeOutline, in order to go though
+        the TreeOutline's SelectionController.
+
+        (WI.TreeElement.treeElementMouseDown): Deleted.
+        Moved handler to TreeOutline, which owns the SelectionController that
+        needs to respond to mouse events.
+
+        * UserInterface/Views/TreeOutline.js:
+        (WI.TreeOutline):
+        (WI.TreeOutline.prototype.get allowsMultipleSelection):
+        (WI.TreeOutline.prototype.set allowsMultipleSelection):
+        (WI.TreeOutline.prototype.get selectedTreeElement):
+        (WI.TreeOutline.prototype.set selectedTreeElement):
+        (WI.TreeOutline.prototype.insertChild):
+        (WI.TreeOutline.prototype.removeChildAtIndex):
+        (WI.TreeOutline.prototype._rememberTreeElement):
+        (WI.TreeOutline.prototype._forgetTreeElement):
+        (WI.TreeOutline.prototype._treeKeyDown):
+        (WI.TreeOutline.prototype.selectionControllerNumberOfItems):
+        (WI.TreeOutline.prototype.selectionControllerSelectionDidChange):
+        (WI.TreeOutline.prototype.selectionControllerNextSelectableIndex):
+        (WI.TreeOutline.prototype.selectionControllerPreviousSelectableIndex):
+        (WI.TreeOutline.prototype.selectTreeElementInternal):
+        (WI.TreeOutline._generateStyleRulesIfNeeded._indexOfTreeElement.previousElement):
+        (WI.TreeOutline._generateStyleRulesIfNeeded):
+
 2018-11-27  Nikita Vasilyev  <[email protected]>
 
         Web Inspector: Experimental Computed panel is unreadable in Dark Mode

Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/SelectionController.js (238598 => 238599)


--- trunk/Source/WebInspectorUI/UserInterface/Controllers/SelectionController.js	2018-11-28 02:16:25 UTC (rev 238598)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/SelectionController.js	2018-11-28 02:55:42 UTC (rev 238599)
@@ -192,15 +192,17 @@
         this._selectedIndexes.clear();
     }
 
+    didInsertItem(index)
+    {
+        this._adjustIndexesAfter(index - 1, 1);
+    }
+
     didRemoveItem(index)
     {
         if (this.hasSelectedItem(index))
             this.deselectItem(index);
 
-        while (index = this._selectedIndexes.indexGreaterThan(index)) {
-            this._selectedIndexes.delete(index);
-            this._selectedIndexes.add(index - 1);
-        }
+        this._adjustIndexesAfter(index, -1);
     }
 
     handleKeyDown(event)
@@ -208,7 +210,7 @@
         if (!this.numberOfItems)
             return false;
 
-        if (event.key === "a" && event.commandOrControlKey()) {
+        if (event.key === "a" && event.commandOrControlKey) {
             this.selectAll();
             return true;
         }
@@ -372,4 +374,12 @@
         let selectedItems = indexes.difference(oldSelectedIndexes);
         this._delegate.selectionControllerSelectionDidChange(this, deselectedItems, selectedItems);
     }
+
+    _adjustIndexesAfter(index, delta)
+    {
+        while (index = this._selectedIndexes.indexGreaterThan(index)) {
+            this._selectedIndexes.delete(index);
+            this._selectedIndexes.add(index + delta);
+        }
+    }
 };

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeElement.js (238598 => 238599)


--- trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeElement.js	2018-11-28 02:16:25 UTC (rev 238598)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeElement.js	2018-11-28 02:55:42 UTC (rev 238599)
@@ -669,16 +669,16 @@
         return true;
     }
 
-    selectOnMouseDown(event)
+    canSelectOnMouseDown(event)
     {
-        super.selectOnMouseDown(event);
-
         if (this._editing)
-            return;
+            return false;
 
         // Prevent selecting the nearest word on double click.
         if (event.detail >= 2)
-            event.preventDefault();
+            return false;
+
+        return true;
     }
 
     ondblclick(event)

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.js (238598 => 238599)


--- trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.js	2018-11-28 02:16:25 UTC (rev 238598)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.js	2018-11-28 02:55:42 UTC (rev 238599)
@@ -298,8 +298,6 @@
             event.preventDefault();
             return;
         }
-
-        element.select();
     }
 
     _onmousemove(event)

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ShaderProgramTreeElement.js (238598 => 238599)


--- trunk/Source/WebInspectorUI/UserInterface/Views/ShaderProgramTreeElement.js	2018-11-28 02:16:25 UTC (rev 238598)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ShaderProgramTreeElement.js	2018-11-28 02:55:42 UTC (rev 238599)
@@ -48,12 +48,9 @@
         this.element.addEventListener("mouseout", this._handleMouseOut.bind(this));
     }
 
-    selectOnMouseDown(event)
+    canSelectOnMouseDown(event)
     {
-        if (this._statusElement.contains(event.target))
-            return;
-
-        super.selectOnMouseDown(event);
+        return !this._statusElement.contains(event.target);
     }
 
     // Private

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TreeElement.js (238598 => 238599)


--- trunk/Source/WebInspectorUI/UserInterface/Views/TreeElement.js	2018-11-28 02:16:25 UTC (rev 238598)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TreeElement.js	2018-11-28 02:55:42 UTC (rev 238599)
@@ -187,6 +187,12 @@
             this.expand();
     }
 
+    canSelectOnMouseDown(event)
+    {
+        // Overridden by subclasses if needed.
+        return true;
+    }
+
     _fireDidChange()
     {
         if (this.treeOutline)
@@ -239,7 +245,6 @@
             if (this.selected)
                 this._listItemNode.classList.add("selected");
 
-            this._listItemNode.addEventListener("mousedown", WI.TreeElement.treeElementMouseDown);
             this._listItemNode.addEventListener("click", WI.TreeElement.treeElementToggled);
             this._listItemNode.addEventListener("dblclick", WI.TreeElement.treeElementDoubleClicked);
 
@@ -279,20 +284,6 @@
             this.treeOutline.soon.updateVirtualizedElements();
     }
 
-    static treeElementMouseDown(event)
-    {
-        var element = event.currentTarget;
-        if (!element || !element.treeElement || !element.treeElement.selectable)
-            return;
-
-        if (element.treeElement.isEventWithinDisclosureTriangle(event)) {
-            event.preventDefault();
-            return;
-        }
-
-        element.treeElement.selectOnMouseDown(event);
-    }
-
     static treeElementToggled(event)
     {
         let element = event.currentTarget;
@@ -526,30 +517,12 @@
 
         treeOutline.processingSelectionChange = true;
 
-        // Prevent dispatching a SelectionDidChange event for the deselected element if
-        // it will be dispatched for the selected element.
-        if (!suppressOnSelect)
-            suppressOnDeselect = true;
+        this.selected = true;
+        treeOutline.selectTreeElementInternal(this, suppressOnSelect, selectedByUser);
 
-        let deselectedElement = treeOutline.selectedTreeElement;
-        if (!this.selected) {
-            if (treeOutline.selectedTreeElement)
-                treeOutline.selectedTreeElement.deselect(suppressOnDeselect);
+        if (!suppressOnSelect && this.onselect)
+            this.onselect(this, selectedByUser);
 
-            this.selected = true;
-            treeOutline.selectedTreeElement = this;
-
-            if (this._listItemNode)
-                this._listItemNode.classList.add("selected");
-        }
-
-        if (!suppressOnSelect) {
-            if (this.onselect)
-                this.onselect(this, selectedByUser);
-
-            treeOutline.dispatchEventToListeners(WI.TreeOutline.Event.SelectionDidChange, {selectedByUser});
-        }
-
         treeOutline.processingSelectionChange = false;
 
         let treeOutlineGroup = WI.TreeOutlineGroup.groupForTreeOutline(treeOutline);
@@ -571,18 +544,11 @@
             return false;
 
         this.selected = false;
-        this.treeOutline.selectedTreeElement = null;
+        this.treeOutline.selectTreeElementInternal(null, suppressOnDeselect);
 
-        if (this._listItemNode)
-            this._listItemNode.classList.remove("selected");
+        if (!suppressOnDeselect && this.ondeselect)
+            this.ondeselect(this);
 
-        if (!suppressOnDeselect) {
-            if (this.ondeselect)
-                this.ondeselect(this);
-
-            this.treeOutline.dispatchEventToListeners(WI.TreeOutline.Event.SelectionDidChange);
-        }
-
         return true;
     }
 

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TreeOutline.js (238598 => 238599)


--- trunk/Source/WebInspectorUI/UserInterface/Views/TreeOutline.js	2018-11-28 02:16:25 UTC (rev 238598)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TreeOutline.js	2018-11-28 02:55:42 UTC (rev 238599)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007, 2013, 2015 Apple Inc.  All rights reserved.
+ * Copyright (C) 2007-2018 Apple Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -37,7 +37,6 @@
         this.element.addEventListener("contextmenu", this._handleContextmenu.bind(this));
 
         this.children = [];
-        this.selectedTreeElement = null;
         this._childrenListNode = this.element;
         this._childrenListNode.removeChildren();
         this._knownTreeElements = [];
@@ -55,6 +54,14 @@
         this._customIndent = false;
         this._selectable = selectable;
 
+        this._cachedNumberOfDescendents = 0;
+        this._selectionController = new WI.SelectionController(this);
+        this._treeElementIndexCache = new Map;
+
+        this._itemWasSelectedByUser = false;
+        this._processingSelectionControllerSelectionDidChange = false;
+        this._suppressNextSelectionDidChangeEvent = false;
+
         this._virtualizedVisibleTreeElements = null;
         this._virtualizedAttachedTreeElements = null;
         this._virtualizedScrollContainer = null;
@@ -64,6 +71,7 @@
 
         this._childrenListNode.tabIndex = 0;
         this._childrenListNode.addEventListener("keydown", this._treeKeyDown.bind(this), true);
+        this._childrenListNode.addEventListener("mousedown", this._handleMouseDown.bind(this));
 
         WI.TreeOutline._generateStyleRulesIfNeeded();
 
@@ -73,6 +81,28 @@
 
     // Public
 
+    get allowsMultipleSelection()
+    {
+        return this._selectionController.allowsMultipleSelection;
+    }
+
+    set allowsMultipleSelection(flag)
+    {
+        this._selectionController.allowsMultipleSelection = flag;
+    }
+
+    get selectedTreeElement()
+    {
+        let selectedIndex = this._selectionController.lastSelectedItem;
+        return this._treeElementAtIndex(selectedIndex) || null;
+    }
+
+    set selectedTreeElement(treeElement)
+    {
+        let index = this._indexOfTreeElement(treeElement);
+        this._selectionController.selectItem(index);
+    }
+
     get hidden()
     {
         return this._hidden;
@@ -242,6 +272,9 @@
 
         if (isFirstChild && this.expanded)
             this.expand();
+
+        let insertionIndex = this.treeOutline._indexOfTreeElement(child.previousSibling) || 0;
+        this.treeOutline._selectionController.didInsertItem(insertionIndex);
     }
 
     removeChildAtIndex(childIndex, suppressOnDeselect, suppressSelectSibling)
@@ -272,6 +305,7 @@
         if (treeOutline) {
             treeOutline._forgetTreeElement(child);
             treeOutline._forgetChildrenRecursive(child);
+            treeOutline._selectionController.didRemoveItem(childIndex);
         }
 
         child._detach();
@@ -378,6 +412,9 @@
 
     _rememberTreeElement(element)
     {
+        this._treeElementIndexCache.clear();
+        this._cachedNumberOfDescendents++;
+
         if (!this._knownTreeElements[element.identifier])
             this._knownTreeElements[element.identifier] = [];
 
@@ -392,6 +429,9 @@
 
     _forgetTreeElement(element)
     {
+        this._treeElementIndexCache.clear();
+        this._cachedNumberOfDescendents--;
+
         if (this.selectedTreeElement === element) {
             element.deselect(true);
             this.selectedTreeElement = null;
@@ -523,7 +563,7 @@
         if (event.target !== this._childrenListNode)
             return;
 
-        if (!this.selectedTreeElement || event.shiftKey || event.metaKey || event.ctrlKey)
+        if (!this.selectedTreeElement || event.commandOrControlKey)
             return;
 
         let isRTL = WI.resolvedLayoutDirection() === WI.LayoutDirection.RTL;
@@ -530,17 +570,8 @@
 
         var handled = false;
         var nextSelectedElement;
-        if (event.keyIdentifier === "Up" && !event.altKey) {
-            nextSelectedElement = this.selectedTreeElement.traversePreviousTreeElement(true);
-            while (nextSelectedElement && !nextSelectedElement.selectable)
-                nextSelectedElement = nextSelectedElement.traversePreviousTreeElement(true);
-            handled = nextSelectedElement ? true : false;
-        } else if (event.keyIdentifier === "Down" && !event.altKey) {
-            nextSelectedElement = this.selectedTreeElement.traverseNextTreeElement(true);
-            while (nextSelectedElement && !nextSelectedElement.selectable)
-                nextSelectedElement = nextSelectedElement.traverseNextTreeElement(true);
-            handled = nextSelectedElement ? true : false;
-        } else if ((!isRTL && event.keyIdentifier === "Left") || (isRTL && event.keyIdentifier === "Right")) {
+
+        if ((!isRTL && event.keyIdentifier === "Left") || (isRTL && event.keyIdentifier === "Right")) {
             if (this.selectedTreeElement.expanded) {
                 if (event.altKey)
                     this.selectedTreeElement.collapseRecursively();
@@ -563,7 +594,12 @@
                 handled = true;
             } else if (this.selectedTreeElement.hasChildren) {
                 handled = true;
-                if (!this.selectedTreeElement.expanded) {
+                if (this.selectedTreeElement.expanded) {
+                    nextSelectedElement = this.selectedTreeElement.children[0];
+                    while (nextSelectedElement && !nextSelectedElement.selectable)
+                        nextSelectedElement = nextSelectedElement.nextSibling;
+                    handled = nextSelectedElement ? true : false;
+                } else {
                     if (event.altKey)
                         this.selectedTreeElement.expandRecursively();
                     else
@@ -587,6 +623,9 @@
                 handled = this.treeOutline.onspace(this.selectedTreeElement);
         }
 
+        if (!handled)
+            handled = this._selectionController.handleKeyDown(event);
+
         if (nextSelectedElement) {
             nextSelectedElement.reveal();
             nextSelectedElement.select(false, true);
@@ -757,8 +796,96 @@
             this._virtualizedScrollContainer.scrollTop = (firstItem + extraRows) * this._virtualizedTreeItemHeight;
     }
 
+    // SelectionController delegate
+
+    selectionControllerNumberOfItems(controller)
+    {
+        return this._cachedNumberOfDescendents;
+    }
+
+    selectionControllerSelectionDidChange(controller, deselectedItems, selectedItems)
+    {
+        this._processingSelectionControllerSelectionDidChange = true;
+
+        for (let index of deselectedItems) {
+            let treeElement = this._treeElementAtIndex(index);
+            console.assert(treeElement, "Missing TreeElement for deselected index " + index);
+            if (treeElement) {
+                treeElement.listItemElement.classList.remove("selected");
+                if (!this._suppressNextSelectionDidChangeEvent)
+                    treeElement.deselect();
+            }
+        }
+
+        for (let index of selectedItems) {
+            let treeElement = this._treeElementAtIndex(index);
+            console.assert(treeElement, "Missing TreeElement for selected index " + index);
+            if (treeElement) {
+                treeElement.listItemElement.classList.add("selected");
+                if (!this._suppressNextSelectionDidChangeEvent)
+                    treeElement.select();
+            }
+        }
+
+        this._processingSelectionControllerSelectionDidChange = false;
+
+        this._dispatchSelectionDidChangeEvent();
+    }
+
+    selectionControllerNextSelectableIndex(controller, index)
+    {
+        let treeElement = this._treeElementAtIndex(index);
+        if (!treeElement)
+            return NaN;
+
+        const skipUnrevealed = true;
+        const stayWithin = null;
+        const dontPopulate = true;
+
+        while (treeElement = treeElement.traverseNextTreeElement(skipUnrevealed, stayWithin, dontPopulate)) {
+            if (treeElement.selectable)
+                return this._indexOfTreeElement(treeElement);
+        }
+
+        return NaN;
+    }
+
+    selectionControllerPreviousSelectableIndex(controller, index)
+    {
+        let treeElement = this._treeElementAtIndex(index);
+        if (!treeElement)
+            return NaN;
+
+        const skipUnrevealed = true;
+        const stayWithin = null;
+        const dontPopulate = true;
+
+        while (treeElement = treeElement.traversePreviousTreeElement(skipUnrevealed, stayWithin, dontPopulate)) {
+            if (treeElement.selectable)
+                return this._indexOfTreeElement(treeElement);
+        }
+
+        return NaN;
+    }
+
     // Protected
 
+    selectTreeElementInternal(treeElement, suppressNotification = false, selectedByUser = false)
+    {
+        if (this._processingSelectionControllerSelectionDidChange)
+            return;
+
+        this._itemWasSelectedByUser = selectedByUser;
+        this._suppressNextSelectionDidChangeEvent = suppressNotification;
+
+        if (this.allowsRepeatSelection && this.selectedTreeElement === treeElement) {
+            this._dispatchSelectionDidChangeEvent();
+            return;
+        }
+
+        this.selectedTreeElement = treeElement;
+    }
+
     treeElementFromEvent(event)
     {
         let scrollContainer = this.element.parentElement;
@@ -855,6 +982,93 @@
         let contextMenu = WI.ContextMenu.createFromEvent(event);
         this.populateContextMenu(contextMenu, event, treeElement);
     }
+
+    _handleMouseDown(event)
+    {
+        let treeElement = this.treeElementFromEvent(event);
+        if (!treeElement || !treeElement.selectable)
+            return;
+
+        if (treeElement.isEventWithinDisclosureTriangle(event)) {
+            event.preventDefault();
+            return;
+        }
+
+        if (!treeElement.canSelectOnMouseDown(event)) {
+            event.preventDefault();
+            return;
+        }
+
+        let index = this._indexOfTreeElement(treeElement);
+        if (isNaN(index))
+            return;
+
+        this._selectionController.handleItemMouseDown(index, event);
+    }
+
+    _indexOfTreeElement(treeElement)
+    {
+        function previousElement(element) {
+            if (element.previousSibling) {
+                element = element.previousSibling;
+                if (element.children.length)
+                    element = element.children.lastValue;
+            } else
+                element = element.parent && element.parent.root ? null : element.parent;
+            return element;
+        }
+
+        let index = 0;
+        let current = treeElement;
+        while (current) {
+            let closestIndex = this._treeElementIndexCache.get(current);
+            if (!isNaN(closestIndex)) {
+                index += closestIndex;
+                break;
+            }
+
+            current = previousElement(current);
+            if (current)
+                index++;
+        }
+
+        if (!this._treeElementIndexCache.has(treeElement))
+            this._treeElementIndexCache.set(treeElement, index);
+
+        return index;
+    }
+
+    _treeElementAtIndex(index)
+    {
+        const skipUnrevealed = false;
+        const stayWithin = null;
+        const dontPopulate = true;
+
+        let current = 0;
+        let treeElement = this.children[0];
+        while (treeElement) {
+            if (current === index)
+                return treeElement;
+
+            treeElement = treeElement.traverseNextTreeElement(skipUnrevealed, stayWithin, dontPopulate);
+            ++current;
+        }
+
+        return null;
+    }
+
+    _dispatchSelectionDidChangeEvent()
+    {
+        let selectedByUser = this._itemWasSelectedByUser;
+        this._itemWasSelectedByUser = false;
+
+        if (this._suppressNextSelectionDidChangeEvent) {
+            this._suppressNextSelectionDidChangeEvent = false;
+            return;
+        }
+
+        this.dispatchEventToListeners(WI.TreeOutline.Event.SelectionDidChange, {selectedByUser});
+    }
 };
 
 WI.TreeOutline._styleElement = null;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to