提交 86c490a1 编写于 作者: J Joao Moreno

make tree events simpler by not exposing nodes

上级 866493ef
......@@ -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<T, TFilterData = void> extends IListOptions<T>, ITreeModelOptions<T, TFilterData> { }
export interface ITreeEvent<T, TFilterData> extends IListEvent<ITreeNode<T, TFilterData>> { }
export interface ITreeContextMenuEvent<T, TFilterData> extends IListContextMenuEvent<ITreeNode<T, TFilterData>> { }
export interface ITreeEvent<T> {
elements: T[];
browserEvent?: UIEvent;
}
export interface ITreeContextMenuEvent<T> {
browserEvent: UIEvent;
element: T | undefined;
anchor: HTMLElement | { x: number; y: number; } | undefined;
}
function asTreeEvent<T>(event: IListEvent<ITreeNode<T, any>>): ITreeEvent<T> {
return {
elements: event.elements.map(node => node.element),
browserEvent: event.browserEvent
};
}
function asTreeContextMenuEvent<T>(event: IListContextMenuEvent<ITreeNode<T, any>>): ITreeContextMenuEvent<T> {
return {
element: event.element.element,
browserEvent: event.browserEvent,
anchor: event.anchor
};
}
export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable {
......@@ -184,15 +208,16 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
protected model: ITreeModel<T, TFilterData, TRef>;
protected disposables: IDisposable[] = [];
readonly onDidChangeCollapseState: Event<ITreeNode<T, TFilterData>>;
readonly onDidChangeRenderNodeCount: Event<ITreeNode<T, TFilterData>>;
readonly onDidChangeFocus: Event<ITreeEvent<T, TFilterData>>;
readonly onDidChangeSelection: Event<ITreeEvent<T, TFilterData>>;
readonly onContextMenu: Event<ITreeContextMenuEvent<T, TFilterData>>;
get onDidChangeFocus(): Event<ITreeEvent<T>> { return mapEvent(this.view.onFocusChange, asTreeEvent); }
get onDidChangeSelection(): Event<ITreeEvent<T>> { return mapEvent(this.view.onSelectionChange, asTreeEvent); }
get onContextMenu(): Event<ITreeContextMenuEvent<T>> { return mapEvent(this.view.onContextMenu, asTreeContextMenuEvent); }
get onDidFocus(): Event<void> { return this.view.onDidFocus; }
get onDidBlur(): Event<void> { return this.view.onDidBlur; }
get onDidChangeCollapseState(): Event<ITreeNode<T, TFilterData>> { return this.model.onDidChangeCollapseState; }
get onDidChangeRenderNodeCount(): Event<ITreeNode<T, TFilterData>> { return this.model.onDidChangeRenderNodeCount; }
get onDidDispose(): Event<void> { return this.view.onDidDispose; }
constructor(
......@@ -208,14 +233,9 @@ export abstract class AbstractTree<T, TFilterData, TRef> 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);
......
......@@ -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<T> {
......@@ -95,6 +95,21 @@ class DataTreeRenderer<T, TFilterData, TTemplateData> implements ITreeRenderer<I
}
}
function asTreeEvent<T>(e: ITreeEvent<IDataTreeNode<T>>): ITreeEvent<T> {
return {
browserEvent: e.browserEvent,
elements: e.elements.map(e => e.element)
};
}
function asTreeContextMenuEvent<T>(e: ITreeContextMenuEvent<IDataTreeNode<T>>): ITreeContextMenuEvent<T> {
return {
browserEvent: e.browserEvent,
element: e.element.element,
anchor: e.anchor
};
}
export class DataTree<T extends NonNullable<any>, TFilterData = void> implements IDisposable {
private tree: ObjectTree<IDataTreeNode<T>, TFilterData>;
......@@ -105,6 +120,15 @@ export class DataTree<T extends NonNullable<any>, TFilterData = void> implements
private disposables: IDisposable[] = [];
get onDidChangeFocus(): Event<ITreeEvent<T>> { return mapEvent(this.tree.onDidChangeFocus, asTreeEvent); }
get onDidChangeSelection(): Event<ITreeEvent<T>> { return mapEvent(this.tree.onDidChangeSelection, asTreeEvent); }
get onContextMenu(): Event<ITreeContextMenuEvent<T>> { return mapEvent(this.tree.onContextMenu, asTreeContextMenuEvent); }
get onDidDOMFocus(): Event<void> { return this.tree.onDidFocus; }
get onDidDOMBlur(): Event<void> { return this.tree.onDidBlur; }
get onDidDispose(): Event<void> { return this.tree.onDidDispose; }
constructor(
container: HTMLElement,
delegate: IListVirtualDelegate<T>,
......@@ -125,7 +149,7 @@ export class DataTree<T extends NonNullable<any>, 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<T extends NonNullable<any>, TFilterData = void> implements
}
}
private onDidChangeCollapseState(treeNode: ITreeNode<IDataTreeNode<T>, any>): void {
private _onDidChangeCollapseState(treeNode: ITreeNode<IDataTreeNode<T>, any>): void {
if (!treeNode.collapsed && treeNode.element.state === DataTreeNodeState.Uninitialized) {
this.refreshNode(treeNode.element);
}
......
......@@ -594,7 +594,7 @@ export class ObjectTreeResourceNavigator<T, TFilterData> extends Disposable {
this._register(this.tree.onDidChangeSelection(e => this.onSelection(e)));
}
private onFocus(e: ITreeEvent<T, TFilterData>): void {
private onFocus(e: ITreeEvent<T>): void {
const focus = this.tree.getFocus();
this.tree.setSelection(focus, e.browserEvent);
......@@ -609,7 +609,7 @@ export class ObjectTreeResourceNavigator<T, TFilterData> extends Disposable {
}
}
private onSelection(e: ITreeEvent<T, TFilterData>): void {
private onSelection(e: ITreeEvent<T>): void {
if (!e.browserEvent || !(e.browserEvent instanceof MouseEvent)) {
return;
}
......
......@@ -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<TreeElement, FilterData>): void {
private onContextMenu(e: ITreeContextMenuEvent<TreeElement>): 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,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册