From 86c490a1e28c5c5aa65970e81089f2a264021e12 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 21 Nov 2018 12:58:56 +0100 Subject: [PATCH] make tree events simpler by not exposing nodes --- src/vs/base/browser/ui/tree/abstractTree.ts | 48 +++++++++++++------ src/vs/base/browser/ui/tree/dataTree.ts | 32 +++++++++++-- src/vs/platform/list/browser/listService.ts | 4 +- .../markers/electron-browser/markersPanel.ts | 8 ++-- 4 files changed, 68 insertions(+), 24 deletions(-) diff --git a/src/vs/base/browser/ui/tree/abstractTree.ts b/src/vs/base/browser/ui/tree/abstractTree.ts index f1ff33750cb..5ca765efa7e 100644 --- a/src/vs/base/browser/ui/tree/abstractTree.ts +++ b/src/vs/base/browser/ui/tree/abstractTree.ts @@ -8,7 +8,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { IListOptions, List, IIdentityProvider, IMultipleSelectionController, IListStyles, IAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; import { IListVirtualDelegate, IListRenderer, IListMouseEvent, IListEvent, IListContextMenuEvent } from 'vs/base/browser/ui/list/list'; import { append, $, toggleClass } from 'vs/base/browser/dom'; -import { Event, Relay, chain } from 'vs/base/common/event'; +import { Event, Relay, chain, mapEvent } from 'vs/base/common/event'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; import { ITreeModel, ITreeNode, ITreeRenderer, ITreeModelOptions } from 'vs/base/browser/ui/tree/tree'; @@ -175,8 +175,32 @@ function isInputElement(e: HTMLElement): boolean { } export interface ITreeOptions extends IListOptions, ITreeModelOptions { } -export interface ITreeEvent extends IListEvent> { } -export interface ITreeContextMenuEvent extends IListContextMenuEvent> { } + +export interface ITreeEvent { + elements: T[]; + browserEvent?: UIEvent; +} + +export interface ITreeContextMenuEvent { + browserEvent: UIEvent; + element: T | undefined; + anchor: HTMLElement | { x: number; y: number; } | undefined; +} + +function asTreeEvent(event: IListEvent>): ITreeEvent { + return { + elements: event.elements.map(node => node.element), + browserEvent: event.browserEvent + }; +} + +function asTreeContextMenuEvent(event: IListContextMenuEvent>): ITreeContextMenuEvent { + return { + element: event.element.element, + browserEvent: event.browserEvent, + anchor: event.anchor + }; +} export abstract class AbstractTree implements IDisposable { @@ -184,15 +208,16 @@ export abstract class AbstractTree implements IDisposable protected model: ITreeModel; protected disposables: IDisposable[] = []; - readonly onDidChangeCollapseState: Event>; - readonly onDidChangeRenderNodeCount: Event>; - readonly onDidChangeFocus: Event>; - readonly onDidChangeSelection: Event>; - - readonly onContextMenu: Event>; + get onDidChangeFocus(): Event> { return mapEvent(this.view.onFocusChange, asTreeEvent); } + get onDidChangeSelection(): Event> { return mapEvent(this.view.onSelectionChange, asTreeEvent); } + get onContextMenu(): Event> { return mapEvent(this.view.onContextMenu, asTreeContextMenuEvent); } get onDidFocus(): Event { return this.view.onDidFocus; } get onDidBlur(): Event { return this.view.onDidBlur; } + + get onDidChangeCollapseState(): Event> { return this.model.onDidChangeCollapseState; } + get onDidChangeRenderNodeCount(): Event> { return this.model.onDidChangeRenderNodeCount; } + get onDidDispose(): Event { return this.view.onDidDispose; } constructor( @@ -208,14 +233,9 @@ export abstract class AbstractTree implements IDisposable this.disposables.push(...treeRenderers); this.view = new List(container, treeDelegate, treeRenderers, createComposedTreeListOptions(options)); - this.onDidChangeFocus = this.view.onFocusChange; - this.onDidChangeSelection = this.view.onSelectionChange; - this.onContextMenu = this.view.onContextMenu; this.model = this.createModel(this.view, options); onDidChangeCollapseStateRelay.input = this.model.onDidChangeCollapseState; - this.onDidChangeCollapseState = this.model.onDidChangeCollapseState; - this.onDidChangeRenderNodeCount = this.model.onDidChangeRenderNodeCount; if (options.mouseSupport !== false) { this.view.onMouseClick(this.onMouseClick, this, this.disposables); diff --git a/src/vs/base/browser/ui/tree/dataTree.ts b/src/vs/base/browser/ui/tree/dataTree.ts index ae1d2d6b7b7..6cdf10ca57d 100644 --- a/src/vs/base/browser/ui/tree/dataTree.ts +++ b/src/vs/base/browser/ui/tree/dataTree.ts @@ -3,12 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ITreeOptions, ComposedTreeDelegate, createComposedTreeListOptions } from 'vs/base/browser/ui/tree/abstractTree'; +import { ITreeOptions, ComposedTreeDelegate, createComposedTreeListOptions, ITreeEvent, ITreeContextMenuEvent } from 'vs/base/browser/ui/tree/abstractTree'; import { ObjectTree } from 'vs/base/browser/ui/tree/objectTree'; import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; import { ITreeElement, ITreeNode, ITreeRenderer } from 'vs/base/browser/ui/tree/tree'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import { Emitter, Event } from 'vs/base/common/event'; +import { Emitter, Event, mapEvent } from 'vs/base/common/event'; import { timeout } from 'vs/base/common/async'; export interface IDataTreeElement { @@ -95,6 +95,21 @@ class DataTreeRenderer implements ITreeRenderer(e: ITreeEvent>): ITreeEvent { + return { + browserEvent: e.browserEvent, + elements: e.elements.map(e => e.element) + }; +} + +function asTreeContextMenuEvent(e: ITreeContextMenuEvent>): ITreeContextMenuEvent { + return { + browserEvent: e.browserEvent, + element: e.element.element, + anchor: e.anchor + }; +} + export class DataTree, TFilterData = void> implements IDisposable { private tree: ObjectTree, TFilterData>; @@ -105,6 +120,15 @@ export class DataTree, TFilterData = void> implements private disposables: IDisposable[] = []; + get onDidChangeFocus(): Event> { return mapEvent(this.tree.onDidChangeFocus, asTreeEvent); } + get onDidChangeSelection(): Event> { return mapEvent(this.tree.onDidChangeSelection, asTreeEvent); } + + get onContextMenu(): Event> { return mapEvent(this.tree.onContextMenu, asTreeContextMenuEvent); } + get onDidDOMFocus(): Event { return this.tree.onDidFocus; } + get onDidDOMBlur(): Event { return this.tree.onDidBlur; } + + get onDidDispose(): Event { return this.tree.onDidDispose; } + constructor( container: HTMLElement, delegate: IListVirtualDelegate, @@ -125,7 +149,7 @@ export class DataTree, TFilterData = void> implements this.nodes.set(null, this.root); - this.tree.onDidChangeCollapseState(this.onDidChangeCollapseState, this, this.disposables); + this.tree.onDidChangeCollapseState(this._onDidChangeCollapseState, this, this.disposables); } layout(height?: number): void { @@ -198,7 +222,7 @@ export class DataTree, TFilterData = void> implements } } - private onDidChangeCollapseState(treeNode: ITreeNode, any>): void { + private _onDidChangeCollapseState(treeNode: ITreeNode, any>): void { if (!treeNode.collapsed && treeNode.element.state === DataTreeNodeState.Uninitialized) { this.refreshNode(treeNode.element); } diff --git a/src/vs/platform/list/browser/listService.ts b/src/vs/platform/list/browser/listService.ts index 9e421c77e72..fb5ad01b72a 100644 --- a/src/vs/platform/list/browser/listService.ts +++ b/src/vs/platform/list/browser/listService.ts @@ -594,7 +594,7 @@ export class ObjectTreeResourceNavigator extends Disposable { this._register(this.tree.onDidChangeSelection(e => this.onSelection(e))); } - private onFocus(e: ITreeEvent): void { + private onFocus(e: ITreeEvent): void { const focus = this.tree.getFocus(); this.tree.setSelection(focus, e.browserEvent); @@ -609,7 +609,7 @@ export class ObjectTreeResourceNavigator extends Disposable { } } - private onSelection(e: ITreeEvent): void { + private onSelection(e: ITreeEvent): void { if (!e.browserEvent || !(e.browserEvent instanceof MouseEvent)) { return; } diff --git a/src/vs/workbench/parts/markers/electron-browser/markersPanel.ts b/src/vs/workbench/parts/markers/electron-browser/markersPanel.ts index aec7d75ffda..c19ab72a7d0 100644 --- a/src/vs/workbench/parts/markers/electron-browser/markersPanel.ts +++ b/src/vs/workbench/parts/markers/electron-browser/markersPanel.ts @@ -305,8 +305,8 @@ export class MarkersPanel extends Panel implements IMarkerFilterController { const markerFocusContextKey = Constants.MarkerFocusContextKey.bindTo(this.tree.contextKeyService); const relatedInformationFocusContextKey = Constants.RelatedInformationFocusContextKey.bindTo(this.tree.contextKeyService); this._register(this.tree.onDidChangeFocus(focus => { - markerFocusContextKey.set(focus.elements.some(e => e.element instanceof Marker)); - relatedInformationFocusContextKey.set(focus.elements.some(e => e.element instanceof RelatedInformation)); + markerFocusContextKey.set(focus.elements.some(e => e instanceof Marker)); + relatedInformationFocusContextKey.set(focus.elements.some(e => e instanceof RelatedInformation)); })); const focusTracker = this._register(dom.trackFocus(this.tree.getHTMLElement())); this._register(focusTracker.onDidBlur(() => { @@ -542,7 +542,7 @@ export class MarkersPanel extends Panel implements IMarkerFilterController { this.rangeHighlightDecorations.highlightRange(selection); } - private onContextMenu(e: ITreeContextMenuEvent): void { + private onContextMenu(e: ITreeContextMenuEvent): void { if (!e.element) { return; } @@ -550,7 +550,7 @@ export class MarkersPanel extends Panel implements IMarkerFilterController { e.browserEvent.preventDefault(); e.browserEvent.stopPropagation(); - this._getMenuActions(e.element.element).then(actions => { + this._getMenuActions(e.element).then(actions => { this.contextMenuService.showContextMenu({ getAnchor: () => e.anchor, getActions: () => actions, -- GitLab