WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
Bug 191483
Web Inspector: TreeOutline should re-use multiple-selection logic from Table
https://bugs.webkit.org/show_bug.cgi?id=191483
Summary
Web Inspector: TreeOutline should re-use multiple-selection logic from Table
Matt Baker
Reported
2018-11-09 12:53:28 PST
Summary: TreeOutline should re-use multiple-selection logic from Table. This will involve creating a new class, ItemSelectionController, which owns an IndexSet of selected items and provides a set of selection operations.
Attachments
Patch
(25.03 KB, patch)
2018-11-27 15:12 PST
,
Matt Baker
no flags
Details
Formatted Diff
Diff
Patch
(22.53 KB, patch)
2018-11-27 16:58 PST
,
Matt Baker
no flags
Details
Formatted Diff
Diff
Patch
(24.25 KB, patch)
2018-11-27 17:52 PST
,
Matt Baker
no flags
Details
Formatted Diff
Diff
Patch
(24.27 KB, patch)
2018-11-27 17:56 PST
,
Matt Baker
no flags
Details
Formatted Diff
Diff
Show Obsolete
(3)
View All
Add attachment
proposed patch, testcase, etc.
Radar WebKit Bug Importer
Comment 1
2018-11-09 12:53:45 PST
<
rdar://problem/45953305
>
Matt Baker
Comment 2
2018-11-27 15:12:37 PST
Created
attachment 355791
[details]
Patch
Devin Rousso
Comment 3
2018-11-27 16:40:11 PST
Comment on
attachment 355791
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=355791&action=review
> Source/WebInspectorUI/UserInterface/Controllers/SelectionController.js:-211 > - if (event.key === "a" && event.commandOrControlKey()) {
Oops :P
> Source/WebInspectorUI/UserInterface/Views/TreeElement.js:-293 > - element.treeElement.selectOnMouseDown(event);
Is `selectOnMouseDown` called anywhere else? I know it's used by `WI.DOMTreeElement` and `WI.ShaderProgramTreeElement`.
> Source/WebInspectorUI/UserInterface/Views/TreeElement.js:514 > let deselectedElement = treeOutline.selectedTreeElement;
This variable is never used, so you could remove it.
> Source/WebInspectorUI/UserInterface/Views/TreeElement.js:517 > + treeOutline.selectTreeElementInternal(this, suppressOnSelect, selectedByUser);
This will have a slightly different effect than what was here before. It will no longer fire an event when the element is already selected, which was not the case previously (it would fire an event even it was already selected (`allowsRepeatSelection` had to have also been `true`). You should move this outside of the `if` (or just remove the `if` altogether): this.selected = true; treeOutline.selectTreeElementInternal(this, suppressOnSelect, selectedByUser);
> Source/WebInspectorUI/UserInterface/Views/TreeOutline.js:59 > + this._treeElementIndexCache = new Map;
Perhaps this would be a good opportunity to create an `IndexMap` (some sort of specialized `BiMap`)?
> Source/WebInspectorUI/UserInterface/Views/TreeOutline.js:102 > + const extendSelection = false;
This defaults to `false`, so you don't need to specify it in the `selectItem` call.
> Source/WebInspectorUI/UserInterface/Views/TreeOutline.js:278 > + this.treeOutline._selectionController.didInsertItem(insertionIndex);
Wow we do this all over the place... why is the `this.treeOutline` this needed? Would `this._selectionController` not suffice? Do we nest `WI.TreeOutline` somewhere?
> Source/WebInspectorUI/UserInterface/Views/TreeOutline.js:576 > + if (this.selectedTreeElement) {
This check isn't necessary, as you should've already bailed above if `!this.selectedTreeElement`.
> Source/WebInspectorUI/UserInterface/Views/TreeOutline.js:631 > + handled = this._selectionController.handleKeyDown(event);
Ah I see how you're using the return value. Nice!
> Source/WebInspectorUI/UserInterface/Views/TreeOutline.js:921 > +
???
> Source/WebInspectorUI/UserInterface/Views/TreeOutline.js:1015 > + let closestIndex = this._treeElementIndexCache.get(current);
Is there a real need for this cache, other than in an effort to boost performance? It seems to me that since we clear it each time we remember/forget `WI.TreeElement`s, there's not much to be gained by having it. I'd just remove it unless it's necessary.
> Source/WebInspectorUI/UserInterface/Views/TreeOutline.js:1038 > + for (let treeElement = this.children[0]; treeElement; treeElement = treeElement.traverseNextTreeElement(skipUnrevealed, null, dontPopulate), ++current) {
Style: wow this is ugly. I'd rework this as a `while`: 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; }
Matt Baker
Comment 4
2018-11-27 16:58:13 PST
Comment on
attachment 355791
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=355791&action=review
>> Source/WebInspectorUI/UserInterface/Views/TreeOutline.js:59 >> + this._treeElementIndexCache = new Map; > > Perhaps this would be a good opportunity to create an `IndexMap` (some sort of specialized `BiMap`)?
I considered this. Once the dust settles I'll take a look at cleaning up/optimizing TreeOutline a bit.
>> Source/WebInspectorUI/UserInterface/Views/TreeOutline.js:921 >> + > > ???
Oops, this is old.
>> Source/WebInspectorUI/UserInterface/Views/TreeOutline.js:1015 >> + let closestIndex = this._treeElementIndexCache.get(current); > > Is there a real need for this cache, other than in an effort to boost performance? It seems to me that since we clear it each time we remember/forget `WI.TreeElement`s, there's not much to be gained by having it. I'd just remove it unless it's necessary.
I'd like to leave it in for now. We can revisit/remove it later if needed.
Matt Baker
Comment 5
2018-11-27 16:58:23 PST
Created
attachment 355823
[details]
Patch
Devin Rousso
Comment 6
2018-11-27 17:43:17 PST
Comment on
attachment 355823
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=355823&action=review
r=me, awesome work!
> Source/WebInspectorUI/UserInterface/Views/TreeElement.js:192 > + return true;
Add "// Overridden by subclasses if needed."
> Source/WebInspectorUI/UserInterface/Views/TreeOutline.js:278 > + if (this.allowsMultipleSelection) { > + let insertionIndex = this._indexOfTreeElement(child.previousSibling) || 0; > + this.treeOutline._selectionController.didInsertItem(insertionIndex); > + }
I think this should be always called. Whenever we add a new item, even if we're not allowing multiple selection, we should update the index of any selected item(s) anywhere in the tree. As an example, if I've selected item 3, and I insert at item 1, my selection should be updated to item 4.
> Source/WebInspectorUI/UserInterface/Views/TreeOutline.js:602 > + if (this.selectedTreeElement.expanded) { > + nextSelectedElement = this.selectedTreeElement.children[0]; > + while (nextSelectedElement && !nextSelectedElement.selectable) > + nextSelectedElement = nextSelectedElement.nextSibling; > + handled = nextSelectedElement ? true : false;
This doesn't match Finder's functionality. Are we sure we want to add this?
> Source/WebInspectorUI/UserInterface/Views/TreeOutline.js:835 > + while (treeElement = treeElement.traverseNextTreeElement(skipUnrevealed, null, dontPopulate)) {
NIT: use `const stayWithin = null;` for this argument instead.
> Source/WebInspectorUI/UserInterface/Views/TreeOutline.js:852 > + while (treeElement = treeElement.traversePreviousTreeElement(skipUnrevealed, null, dontPopulate)) {
Ditto (835)
> Source/WebInspectorUI/UserInterface/Views/TreeOutline.js:862 > + selectTreeElementInternal(treeElement, suppressNotification = false, selectedByUser = false)
I'd rather you use an optional object instead of defaulted parameters: selectTreeElementInternal(treeElement, {suppressNotification, selectedByUser} = {})
Matt Baker
Comment 7
2018-11-27 17:52:17 PST
Created
attachment 355830
[details]
Patch
Matt Baker
Comment 8
2018-11-27 17:56:55 PST
Created
attachment 355831
[details]
Patch
Devin Rousso
Comment 9
2018-11-27 18:02:18 PST
Comment on
attachment 355831
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=355831&action=review
r=me, well done!
> Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.js:-302 > - element.select();
Considering your changes to `WI.TreeOutline`, you could remove this entire event listener.
> Source/WebInspectorUI/UserInterface/Views/TreeOutline.js:601 > + if (this.selectedTreeElement.expanded) { > + nextSelectedElement = this.selectedTreeElement.children[0]; > + while (nextSelectedElement && !nextSelectedElement.selectable) > + nextSelectedElement = nextSelectedElement.nextSibling; > + handled = nextSelectedElement ? true : false;
This doesn't match Finder's functionality. Are we sure we want to add this?
> Source/WebInspectorUI/UserInterface/Views/TreeOutline.js:873 > + selectTreeElementInternal(treeElement, suppressNotification = false, selectedByUser = false)
I'd rather you use an optional object instead of defaulted parameters: selectTreeElementInternal(treeElement, {suppressNotification, selectedByUser} = {})
> Source/WebInspectorUI/UserInterface/Views/TreeOutline.js:875 > + if (this._processingSelectionControllerSelectionDidChange)
All of this early-return interleaving is a bit crazy. We definitely need some tests for all of these different cases 😅
WebKit Commit Bot
Comment 10
2018-11-27 18:55:49 PST
Comment on
attachment 355831
[details]
Patch Clearing flags on attachment: 355831 Committed
r238599
: <
https://trac.webkit.org/changeset/238599
>
WebKit Commit Bot
Comment 11
2018-11-27 18:55:51 PST
All reviewed patches have been landed. Closing bug.
Nikita Vasilyev
Comment 12
2018-11-30 17:35:31 PST
Next time please consider doing something like this behind the experimental flag. This broke debugger completely and introduced several bugs in the Elements tab.
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug