mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-03-23 21:30:29 -04:00
Initial VS Code 1.19 source merge (#571)
* Initial 1.19 xcopy * Fix yarn build * Fix numerous build breaks * Next batch of build break fixes * More build break fixes * Runtime breaks * Additional post merge fixes * Fix windows setup file * Fix test failures. * Update license header blocks to refer to source eula
This commit is contained in:
@@ -77,14 +77,6 @@
|
||||
background-image: url('expanded.svg');
|
||||
}
|
||||
|
||||
.monaco-tree .monaco-tree-rows.show-twisties > .monaco-tree-row.has-children.selected.expanded > .content:before {
|
||||
background-image: url('expanded-hc.svg');
|
||||
}
|
||||
|
||||
.monaco-tree .monaco-tree-rows.show-twisties > .monaco-tree-row.has-children.selected > .content:before {
|
||||
background-image: url('collapsed-hc.svg');
|
||||
}
|
||||
|
||||
.monaco-tree .monaco-tree-rows > .monaco-tree-row.has-children.loading > .content:before {
|
||||
background-image: url('loading.svg');
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
import WinJS = require('vs/base/common/winjs.base');
|
||||
import Touch = require('vs/base/browser/touch');
|
||||
import Events = require('vs/base/common/eventEmitter');
|
||||
import Mouse = require('vs/base/browser/mouseEvent');
|
||||
import Keyboard = require('vs/base/browser/keyboardEvent');
|
||||
import { INavigator } from 'vs/base/common/iterator';
|
||||
@@ -14,15 +13,18 @@ import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
||||
import Event from 'vs/base/common/event';
|
||||
import { IAction, IActionItem } from 'vs/base/common/actions';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { IItemCollapseEvent, IItemExpandEvent } from 'vs/base/parts/tree/browser/treeModel';
|
||||
|
||||
export interface ITree extends Events.IEventEmitter {
|
||||
export interface ITree {
|
||||
|
||||
emit(eventType: string, data?: any): void;
|
||||
|
||||
onDOMFocus: Event<void>;
|
||||
onDOMBlur: Event<void>;
|
||||
onHighlightChange: Event<void>;
|
||||
onDispose: Event<void>;
|
||||
onDidFocus: Event<void>;
|
||||
onDidBlur: Event<void>;
|
||||
onDidChangeFocus: Event<IFocusEvent>;
|
||||
onDidChangeSelection: Event<ISelectionEvent>;
|
||||
onDidChangeHighlight: Event<IHighlightEvent>;
|
||||
onDidExpandItem: Event<IItemExpandEvent>;
|
||||
onDidCollapseItem: Event<IItemCollapseEvent>;
|
||||
onDidDispose: Event<void>;
|
||||
|
||||
/**
|
||||
* Returns the tree's DOM element.
|
||||
@@ -101,6 +103,13 @@ export interface ITree extends Events.IEventEmitter {
|
||||
*/
|
||||
collapseAll(elements?: any[], recursive?: boolean): WinJS.Promise;
|
||||
|
||||
/**
|
||||
* Collapses several elements.
|
||||
* Collapses all elements at the greatest tree depth that has expanded elements.
|
||||
* The returned promise returns a boolean for whether the elements were collapsed or not.
|
||||
*/
|
||||
collapseDeepestExpandedLevel(): WinJS.Promise;
|
||||
|
||||
/**
|
||||
* Toggles an element's expansion state.
|
||||
*/
|
||||
|
||||
@@ -7,15 +7,15 @@
|
||||
import 'vs/css!./tree';
|
||||
import WinJS = require('vs/base/common/winjs.base');
|
||||
import TreeDefaults = require('vs/base/parts/tree/browser/treeDefaults');
|
||||
import Events = require('vs/base/common/eventEmitter');
|
||||
import Model = require('vs/base/parts/tree/browser/treeModel');
|
||||
import View = require('./treeView');
|
||||
import _ = require('vs/base/parts/tree/browser/tree');
|
||||
import { INavigator, MappedNavigator } from 'vs/base/common/iterator';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import Lifecycle = require('vs/base/common/lifecycle');
|
||||
import Event, { Emitter, Relay } from 'vs/base/common/event';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { mixin } from 'vs/base/common/objects';
|
||||
import { ISelectionEvent, IFocusEvent, IHighlightEvent } from 'vs/base/parts/tree/browser/tree';
|
||||
import { IItemCollapseEvent, IItemExpandEvent } from 'vs/base/parts/tree/browser/treeModel';
|
||||
|
||||
export class TreeContext implements _.ITreeContext {
|
||||
|
||||
@@ -61,42 +61,37 @@ const defaultStyles: _.ITreeStyles = {
|
||||
listDropBackground: Color.fromHex('#383B3D')
|
||||
};
|
||||
|
||||
export class Tree extends Events.EventEmitter implements _.ITree {
|
||||
export class Tree implements _.ITree {
|
||||
|
||||
private container: HTMLElement;
|
||||
private configuration: _.ITreeConfiguration;
|
||||
private options: _.ITreeOptions;
|
||||
|
||||
private context: _.ITreeContext;
|
||||
private model: Model.TreeModel;
|
||||
private view: View.TreeView;
|
||||
|
||||
private _onDispose: Emitter<void>;
|
||||
private _onHighlightChange: Emitter<void>;
|
||||
|
||||
private toDispose: Lifecycle.IDisposable[];
|
||||
private _onDidChangeFocus = new Relay<IFocusEvent>();
|
||||
readonly onDidChangeFocus: Event<IFocusEvent> = this._onDidChangeFocus.event;
|
||||
private _onDidChangeSelection = new Relay<ISelectionEvent>();
|
||||
readonly onDidChangeSelection: Event<ISelectionEvent> = this._onDidChangeSelection.event;
|
||||
private _onHighlightChange = new Relay<IHighlightEvent>();
|
||||
readonly onDidChangeHighlight: Event<IHighlightEvent> = this._onHighlightChange.event;
|
||||
private _onDidExpandItem = new Relay<IItemExpandEvent>();
|
||||
readonly onDidExpandItem: Event<IItemExpandEvent> = this._onDidExpandItem.event;
|
||||
private _onDidCollapseItem = new Relay<IItemCollapseEvent>();
|
||||
readonly onDidCollapseItem: Event<IItemCollapseEvent> = this._onDidCollapseItem.event;
|
||||
private _onDispose = new Emitter<void>();
|
||||
readonly onDidDispose: Event<void> = this._onDispose.event;
|
||||
|
||||
constructor(container: HTMLElement, configuration: _.ITreeConfiguration, options: _.ITreeOptions = {}) {
|
||||
super();
|
||||
|
||||
this.toDispose = [];
|
||||
|
||||
this._onDispose = new Emitter<void>();
|
||||
this._onHighlightChange = new Emitter<void>();
|
||||
|
||||
this.toDispose.push(this._onDispose, this._onHighlightChange);
|
||||
|
||||
this.container = container;
|
||||
this.configuration = configuration;
|
||||
this.options = options;
|
||||
mixin(this.options, defaultStyles, false);
|
||||
mixin(options, defaultStyles, false);
|
||||
|
||||
this.options.twistiePixels = typeof this.options.twistiePixels === 'number' ? this.options.twistiePixels : 32;
|
||||
this.options.showTwistie = this.options.showTwistie === false ? false : true;
|
||||
this.options.indentPixels = typeof this.options.indentPixels === 'number' ? this.options.indentPixels : 12;
|
||||
this.options.alwaysFocused = this.options.alwaysFocused === true ? true : false;
|
||||
this.options.useShadows = this.options.useShadows === false ? false : true;
|
||||
this.options.paddingOnRow = this.options.paddingOnRow === false ? false : true;
|
||||
options.twistiePixels = typeof options.twistiePixels === 'number' ? options.twistiePixels : 32;
|
||||
options.showTwistie = options.showTwistie === false ? false : true;
|
||||
options.indentPixels = typeof options.indentPixels === 'number' ? options.indentPixels : 12;
|
||||
options.alwaysFocused = options.alwaysFocused === true ? true : false;
|
||||
options.useShadows = options.useShadows === false ? false : true;
|
||||
options.paddingOnRow = options.paddingOnRow === false ? false : true;
|
||||
|
||||
this.context = new TreeContext(this, configuration, options);
|
||||
this.model = new Model.TreeModel(this.context);
|
||||
@@ -104,32 +99,25 @@ export class Tree extends Events.EventEmitter implements _.ITree {
|
||||
|
||||
this.view.setModel(this.model);
|
||||
|
||||
this.addEmitter(this.model);
|
||||
this.addEmitter(this.view);
|
||||
|
||||
this.toDispose.push(this.model.addListener('highlight', () => this._onHighlightChange.fire()));
|
||||
this._onDidChangeFocus.input = this.model.onDidFocus;
|
||||
this._onDidChangeSelection.input = this.model.onDidSelect;
|
||||
this._onHighlightChange.input = this.model.onDidHighlight;
|
||||
this._onDidExpandItem.input = this.model.onDidExpandItem;
|
||||
this._onDidCollapseItem.input = this.model.onDidCollapseItem;
|
||||
}
|
||||
|
||||
public style(styles: _.ITreeStyles): void {
|
||||
this.view.applyStyles(styles);
|
||||
}
|
||||
|
||||
get onDOMFocus(): Event<void> {
|
||||
get onDidFocus(): Event<void> {
|
||||
return this.view && this.view.onDOMFocus;
|
||||
}
|
||||
|
||||
get onDOMBlur(): Event<void> {
|
||||
get onDidBlur(): Event<void> {
|
||||
return this.view && this.view.onDOMBlur;
|
||||
}
|
||||
|
||||
get onHighlightChange(): Event<void> {
|
||||
return this._onHighlightChange && this._onHighlightChange.event;
|
||||
}
|
||||
|
||||
get onDispose(): Event<void> {
|
||||
return this._onDispose && this._onDispose.event;
|
||||
}
|
||||
|
||||
public getHTMLElement(): HTMLElement {
|
||||
return this.view.getHTMLElement();
|
||||
}
|
||||
@@ -186,6 +174,10 @@ export class Tree extends Events.EventEmitter implements _.ITree {
|
||||
return this.model.collapseAll(elements, recursive);
|
||||
}
|
||||
|
||||
public collapseDeepestExpandedLevel(): WinJS.Promise {
|
||||
return this.model.collapseDeepestExpandedLevel();
|
||||
}
|
||||
|
||||
public toggleExpansion(element: any, recursive: boolean = false): WinJS.Promise {
|
||||
return this.model.toggleExpansion(element, recursive);
|
||||
}
|
||||
@@ -380,8 +372,11 @@ export class Tree extends Events.EventEmitter implements _.ITree {
|
||||
this.view = null;
|
||||
}
|
||||
|
||||
this.toDispose = Lifecycle.dispose(this.toDispose);
|
||||
|
||||
super.dispose();
|
||||
this._onDidChangeFocus.dispose();
|
||||
this._onDidChangeSelection.dispose();
|
||||
this._onHighlightChange.dispose();
|
||||
this._onDidExpandItem.dispose();
|
||||
this._onDidCollapseItem.dispose();
|
||||
this._onDispose.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,31 +9,34 @@ import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { IDisposable, combinedDisposable } from 'vs/base/common/lifecycle';
|
||||
import arrays = require('vs/base/common/arrays');
|
||||
import { INavigator } from 'vs/base/common/iterator';
|
||||
import Events = require('vs/base/common/eventEmitter');
|
||||
import WinJS = require('vs/base/common/winjs.base');
|
||||
import _ = require('./tree');
|
||||
import Event, { Emitter, once, EventMultiplexer, Relay } from 'vs/base/common/event';
|
||||
|
||||
interface IMap<T> { [id: string]: T; }
|
||||
interface IItemMap extends IMap<Item> { }
|
||||
interface ITraitMap extends IMap<IItemMap> { }
|
||||
|
||||
export class LockData extends Events.EventEmitter {
|
||||
export class LockData {
|
||||
|
||||
private _item: Item;
|
||||
private _onDispose = new Emitter<void>();
|
||||
readonly onDispose: Event<void> = this._onDispose.event;
|
||||
|
||||
constructor(item: Item) {
|
||||
super();
|
||||
|
||||
this._item = item;
|
||||
}
|
||||
|
||||
public get item(): Item {
|
||||
get item(): Item {
|
||||
return this._item;
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.emit('unlock');
|
||||
super.dispose();
|
||||
dispose(): void {
|
||||
if (this._onDispose) {
|
||||
this._onDispose.fire();
|
||||
this._onDispose.dispose();
|
||||
this._onDispose = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +87,7 @@ export class Lock {
|
||||
var unbindListener: IDisposable;
|
||||
|
||||
return new WinJS.TPromise((c, e) => {
|
||||
unbindListener = lock.addOneTimeListener('unlock', () => {
|
||||
unbindListener = once(lock.onDispose)(() => {
|
||||
return this.run(item, fn).then(c, e);
|
||||
});
|
||||
}, () => { unbindListener.dispose(); });
|
||||
@@ -126,19 +129,56 @@ export class Lock {
|
||||
}
|
||||
}
|
||||
|
||||
export class ItemRegistry extends Events.EventEmitter {
|
||||
export class ItemRegistry {
|
||||
|
||||
private _isDisposed = false;
|
||||
private items: IMap<{ item: Item; disposable: IDisposable; }>;
|
||||
|
||||
private _onDidRevealItem = new EventMultiplexer<IItemRevealEvent>();
|
||||
readonly onDidRevealItem: Event<IItemRevealEvent> = this._onDidRevealItem.event;
|
||||
private _onExpandItem = new EventMultiplexer<IItemExpandEvent>();
|
||||
readonly onExpandItem: Event<IItemExpandEvent> = this._onExpandItem.event;
|
||||
private _onDidExpandItem = new EventMultiplexer<IItemExpandEvent>();
|
||||
readonly onDidExpandItem: Event<IItemExpandEvent> = this._onDidExpandItem.event;
|
||||
private _onCollapseItem = new EventMultiplexer<IItemCollapseEvent>();
|
||||
readonly onCollapseItem: Event<IItemCollapseEvent> = this._onCollapseItem.event;
|
||||
private _onDidCollapseItem = new EventMultiplexer<IItemCollapseEvent>();
|
||||
readonly onDidCollapseItem: Event<IItemCollapseEvent> = this._onDidCollapseItem.event;
|
||||
private _onDidAddTraitItem = new EventMultiplexer<IItemTraitEvent>();
|
||||
readonly onDidAddTraitItem: Event<IItemTraitEvent> = this._onDidAddTraitItem.event;
|
||||
private _onDidRemoveTraitItem = new EventMultiplexer<IItemCollapseEvent>();
|
||||
readonly onDidRemoveTraitItem: Event<IItemCollapseEvent> = this._onDidRemoveTraitItem.event;
|
||||
private _onDidRefreshItem = new EventMultiplexer<Item>();
|
||||
readonly onDidRefreshItem: Event<Item> = this._onDidRefreshItem.event;
|
||||
private _onRefreshItemChildren = new EventMultiplexer<IItemChildrenRefreshEvent>();
|
||||
readonly onRefreshItemChildren: Event<IItemChildrenRefreshEvent> = this._onRefreshItemChildren.event;
|
||||
private _onDidRefreshItemChildren = new EventMultiplexer<IItemChildrenRefreshEvent>();
|
||||
readonly onDidRefreshItemChildren: Event<IItemChildrenRefreshEvent> = this._onDidRefreshItemChildren.event;
|
||||
private _onDidDisposeItem = new EventMultiplexer<Item>();
|
||||
readonly onDidDisposeItem: Event<Item> = this._onDidDisposeItem.event;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.items = {};
|
||||
}
|
||||
|
||||
public register(item: Item): void {
|
||||
Assert.ok(!this.isRegistered(item.id), 'item already registered: ' + item.id);
|
||||
this.items[item.id] = { item, disposable: this.addEmitter(item) };
|
||||
|
||||
const disposable = combinedDisposable([
|
||||
this._onDidRevealItem.add(item.onDidReveal),
|
||||
this._onExpandItem.add(item.onExpand),
|
||||
this._onDidExpandItem.add(item.onDidExpand),
|
||||
this._onCollapseItem.add(item.onCollapse),
|
||||
this._onDidCollapseItem.add(item.onDidCollapse),
|
||||
this._onDidAddTraitItem.add(item.onDidAddTrait),
|
||||
this._onDidRemoveTraitItem.add(item.onDidRemoveTrait),
|
||||
this._onDidRefreshItem.add(item.onDidRefresh),
|
||||
this._onRefreshItemChildren.add(item.onRefreshChildren),
|
||||
this._onDidRefreshItemChildren.add(item.onDidRefreshChildren),
|
||||
this._onDidDisposeItem.add(item.onDidDispose)
|
||||
]);
|
||||
|
||||
this.items[item.id] = { item, disposable };
|
||||
}
|
||||
|
||||
public deregister(item: Item): void {
|
||||
@@ -157,8 +197,19 @@ export class ItemRegistry extends Events.EventEmitter {
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
super.dispose();
|
||||
this.items = null;
|
||||
|
||||
this._onDidRevealItem.dispose();
|
||||
this._onExpandItem.dispose();
|
||||
this._onDidExpandItem.dispose();
|
||||
this._onCollapseItem.dispose();
|
||||
this._onDidCollapseItem.dispose();
|
||||
this._onDidAddTraitItem.dispose();
|
||||
this._onDidRemoveTraitItem.dispose();
|
||||
this._onDidRefreshItem.dispose();
|
||||
this._onRefreshItemChildren.dispose();
|
||||
this._onDidRefreshItemChildren.dispose();
|
||||
|
||||
this._isDisposed = true;
|
||||
}
|
||||
|
||||
@@ -174,7 +225,6 @@ export interface IBaseItemEvent {
|
||||
export interface IItemRefreshEvent extends IBaseItemEvent { }
|
||||
export interface IItemExpandEvent extends IBaseItemEvent { }
|
||||
export interface IItemCollapseEvent extends IBaseItemEvent { }
|
||||
export interface IItemDisposeEvent extends IBaseItemEvent { }
|
||||
|
||||
export interface IItemTraitEvent extends IBaseItemEvent {
|
||||
trait: string;
|
||||
@@ -188,7 +238,7 @@ export interface IItemChildrenRefreshEvent extends IBaseItemEvent {
|
||||
isNested: boolean;
|
||||
}
|
||||
|
||||
export class Item extends Events.EventEmitter {
|
||||
export class Item {
|
||||
|
||||
private registry: ItemRegistry;
|
||||
private context: _.ITreeContext;
|
||||
@@ -206,8 +256,6 @@ export class Item extends Events.EventEmitter {
|
||||
public firstChild: Item;
|
||||
public lastChild: Item;
|
||||
|
||||
private userContent: HTMLElement;
|
||||
|
||||
private height: number;
|
||||
private depth: number;
|
||||
|
||||
@@ -216,11 +264,34 @@ export class Item extends Events.EventEmitter {
|
||||
|
||||
private traits: { [trait: string]: boolean; };
|
||||
|
||||
private _onDidCreate = new Emitter<Item>();
|
||||
readonly onDidCreate: Event<Item> = this._onDidCreate.event;
|
||||
private _onDidReveal = new Emitter<IItemRevealEvent>();
|
||||
readonly onDidReveal: Event<IItemRevealEvent> = this._onDidReveal.event;
|
||||
private _onExpand = new Emitter<IItemExpandEvent>();
|
||||
readonly onExpand: Event<IItemExpandEvent> = this._onExpand.event;
|
||||
private _onDidExpand = new Emitter<IItemExpandEvent>();
|
||||
readonly onDidExpand: Event<IItemExpandEvent> = this._onDidExpand.event;
|
||||
private _onCollapse = new Emitter<IItemCollapseEvent>();
|
||||
readonly onCollapse: Event<IItemCollapseEvent> = this._onCollapse.event;
|
||||
private _onDidCollapse = new Emitter<IItemCollapseEvent>();
|
||||
readonly onDidCollapse: Event<IItemCollapseEvent> = this._onDidCollapse.event;
|
||||
private _onDidAddTrait = new Emitter<IItemTraitEvent>();
|
||||
readonly onDidAddTrait: Event<IItemTraitEvent> = this._onDidAddTrait.event;
|
||||
private _onDidRemoveTrait = new Emitter<IItemCollapseEvent>();
|
||||
readonly onDidRemoveTrait: Event<IItemCollapseEvent> = this._onDidRemoveTrait.event;
|
||||
private _onDidRefresh = new Emitter<Item>();
|
||||
readonly onDidRefresh: Event<Item> = this._onDidRefresh.event;
|
||||
private _onRefreshChildren = new Emitter<IItemChildrenRefreshEvent>();
|
||||
readonly onRefreshChildren: Event<IItemChildrenRefreshEvent> = this._onRefreshChildren.event;
|
||||
private _onDidRefreshChildren = new Emitter<IItemChildrenRefreshEvent>();
|
||||
readonly onDidRefreshChildren: Event<IItemChildrenRefreshEvent> = this._onDidRefreshChildren.event;
|
||||
private _onDidDispose = new Emitter<Item>();
|
||||
readonly onDidDispose: Event<Item> = this._onDidDispose.event;
|
||||
|
||||
private _isDisposed: boolean;
|
||||
|
||||
constructor(id: string, registry: ItemRegistry, context: _.ITreeContext, lock: Lock, element: any) {
|
||||
super();
|
||||
|
||||
this.registry = registry;
|
||||
this.context = context;
|
||||
this.lock = lock;
|
||||
@@ -238,12 +309,11 @@ export class Item extends Events.EventEmitter {
|
||||
this.firstChild = null;
|
||||
this.lastChild = null;
|
||||
|
||||
this.userContent = null;
|
||||
this.traits = {};
|
||||
this.depth = 0;
|
||||
this.expanded = this.context.dataSource.shouldAutoexpand && this.context.dataSource.shouldAutoexpand(this.context.tree, element);
|
||||
|
||||
this.emit('item:create', { item: this });
|
||||
this._onDidCreate.fire(this);
|
||||
|
||||
this.visible = this._isVisible();
|
||||
this.height = this._getHeight();
|
||||
@@ -281,7 +351,7 @@ export class Item extends Events.EventEmitter {
|
||||
|
||||
public reveal(relativeTop: number = null): void {
|
||||
var eventData: IItemRevealEvent = { item: this, relativeTop: relativeTop };
|
||||
this.emit('item:reveal', eventData);
|
||||
this._onDidReveal.fire(eventData);
|
||||
}
|
||||
|
||||
public expand(): WinJS.Promise {
|
||||
@@ -292,7 +362,7 @@ export class Item extends Events.EventEmitter {
|
||||
var result = this.lock.run(this, () => {
|
||||
var eventData: IItemExpandEvent = { item: this };
|
||||
var result: WinJS.Promise;
|
||||
this.emit('item:expanding', eventData);
|
||||
this._onExpand.fire(eventData);
|
||||
|
||||
if (this.needsChildrenRefresh) {
|
||||
result = this.refreshChildren(false, true, true);
|
||||
@@ -302,7 +372,7 @@ export class Item extends Events.EventEmitter {
|
||||
|
||||
return result.then(() => {
|
||||
this._setExpanded(true);
|
||||
this.emit('item:expanded', eventData);
|
||||
this._onDidExpand.fire(eventData);
|
||||
return true;
|
||||
});
|
||||
});
|
||||
@@ -337,9 +407,9 @@ export class Item extends Events.EventEmitter {
|
||||
|
||||
return this.lock.run(this, () => {
|
||||
var eventData: IItemCollapseEvent = { item: this };
|
||||
this.emit('item:collapsing', eventData);
|
||||
this._onCollapse.fire(eventData);
|
||||
this._setExpanded(false);
|
||||
this.emit('item:collapsed', eventData);
|
||||
this._onDidCollapse.fire(eventData);
|
||||
|
||||
return WinJS.TPromise.as(true);
|
||||
});
|
||||
@@ -349,13 +419,13 @@ export class Item extends Events.EventEmitter {
|
||||
public addTrait(trait: string): void {
|
||||
var eventData: IItemTraitEvent = { item: this, trait: trait };
|
||||
this.traits[trait] = true;
|
||||
this.emit('item:addTrait', eventData);
|
||||
this._onDidAddTrait.fire(eventData);
|
||||
}
|
||||
|
||||
public removeTrait(trait: string): void {
|
||||
var eventData: IItemTraitEvent = { item: this, trait: trait };
|
||||
delete this.traits[trait];
|
||||
this.emit('item:removeTrait', eventData);
|
||||
this._onDidRemoveTrait.fire(eventData);
|
||||
}
|
||||
|
||||
public hasTrait(trait: string): boolean {
|
||||
@@ -387,7 +457,7 @@ export class Item extends Events.EventEmitter {
|
||||
|
||||
var doRefresh = () => {
|
||||
var eventData: IItemChildrenRefreshEvent = { item: this, isNested: safe };
|
||||
this.emit('item:childrenRefreshing', eventData);
|
||||
this._onRefreshChildren.fire(eventData);
|
||||
|
||||
var childrenPromise: WinJS.Promise;
|
||||
if (this.doesHaveChildren) {
|
||||
@@ -443,20 +513,18 @@ export class Item extends Events.EventEmitter {
|
||||
|
||||
return result
|
||||
.then(null, onUnexpectedError)
|
||||
.then(() => this.emit('item:childrenRefreshed', eventData));
|
||||
.then(() => this._onDidRefreshChildren.fire(eventData));
|
||||
};
|
||||
|
||||
return safe ? doRefresh() : this.lock.run(this, doRefresh);
|
||||
}
|
||||
|
||||
private doRefresh(recursive: boolean, safe: boolean = false): WinJS.Promise {
|
||||
var eventData: IItemRefreshEvent = { item: this };
|
||||
|
||||
this.doesHaveChildren = this.context.dataSource.hasChildren(this.context.tree, this.element);
|
||||
this.height = this._getHeight();
|
||||
this.setVisible(this._isVisible());
|
||||
|
||||
this.emit('item:refresh', eventData);
|
||||
this._onDidRefresh.fire(this);
|
||||
|
||||
return this.refreshChildren(recursive, safe);
|
||||
}
|
||||
@@ -486,6 +554,17 @@ export class Item extends Events.EventEmitter {
|
||||
return result;
|
||||
}
|
||||
|
||||
public getChildren(): Item[] {
|
||||
var child = this.firstChild;
|
||||
var results = [];
|
||||
while (child) {
|
||||
results.push(child);
|
||||
child = child.next;
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private isAncestorOf(item: Item): boolean {
|
||||
while (item) {
|
||||
if (item.id === this.id) {
|
||||
@@ -594,11 +673,22 @@ export class Item extends Events.EventEmitter {
|
||||
this.firstChild = null;
|
||||
this.lastChild = null;
|
||||
|
||||
var eventData: IItemDisposeEvent = { item: this };
|
||||
this.emit('item:dispose', eventData);
|
||||
this._onDidDispose.fire(this);
|
||||
|
||||
this.registry.deregister(this);
|
||||
super.dispose();
|
||||
|
||||
this._onDidCreate.dispose();
|
||||
this._onDidReveal.dispose();
|
||||
this._onExpand.dispose();
|
||||
this._onDidExpand.dispose();
|
||||
this._onCollapse.dispose();
|
||||
this._onDidCollapse.dispose();
|
||||
this._onDidAddTrait.dispose();
|
||||
this._onDidRemoveTrait.dispose();
|
||||
this._onDidRefresh.dispose();
|
||||
this._onRefreshChildren.dispose();
|
||||
this._onDidRefreshChildren.dispose();
|
||||
this._onDidDispose.dispose();
|
||||
|
||||
this._isDisposed = true;
|
||||
}
|
||||
@@ -647,13 +737,21 @@ export class TreeNavigator implements INavigator<Item> {
|
||||
static lastDescendantOf(item: Item): Item {
|
||||
if (!item) {
|
||||
return null;
|
||||
} else {
|
||||
if (!(item instanceof RootItem) && (!item.isVisible() || !item.isExpanded() || item.lastChild === null)) {
|
||||
return item;
|
||||
} else {
|
||||
return TreeNavigator.lastDescendantOf(item.lastChild);
|
||||
}
|
||||
}
|
||||
|
||||
if (item instanceof RootItem) {
|
||||
return TreeNavigator.lastDescendantOf(item.lastChild);
|
||||
}
|
||||
|
||||
if (!item.isVisible()) {
|
||||
return TreeNavigator.lastDescendantOf(item.previous);
|
||||
}
|
||||
|
||||
if (!item.isExpanded() || item.lastChild === null) {
|
||||
return item;
|
||||
}
|
||||
|
||||
return TreeNavigator.lastDescendantOf(item.lastChild);
|
||||
}
|
||||
|
||||
constructor(item: Item, subTreeOnly: boolean = true) {
|
||||
@@ -772,7 +870,7 @@ export interface IRefreshEvent extends IBaseEvent {
|
||||
recursive: boolean;
|
||||
}
|
||||
|
||||
export class TreeModel extends Events.EventEmitter {
|
||||
export class TreeModel {
|
||||
|
||||
private context: _.ITreeContext;
|
||||
private lock: Lock;
|
||||
@@ -781,9 +879,45 @@ export class TreeModel extends Events.EventEmitter {
|
||||
private registryDisposable: IDisposable;
|
||||
private traitsToItems: ITraitMap;
|
||||
|
||||
constructor(context: _.ITreeContext) {
|
||||
super();
|
||||
private _onSetInput = new Emitter<IInputEvent>();
|
||||
readonly onSetInput: Event<IInputEvent> = this._onSetInput.event;
|
||||
private _onDidSetInput = new Emitter<IInputEvent>();
|
||||
readonly onDidSetInput: Event<IInputEvent> = this._onDidSetInput.event;
|
||||
private _onRefresh = new Emitter<IRefreshEvent>();
|
||||
readonly onRefresh: Event<IRefreshEvent> = this._onRefresh.event;
|
||||
private _onDidRefresh = new Emitter<IRefreshEvent>();
|
||||
readonly onDidRefresh: Event<IRefreshEvent> = this._onDidRefresh.event;
|
||||
private _onDidHighlight = new Emitter<_.IHighlightEvent>();
|
||||
readonly onDidHighlight: Event<_.IHighlightEvent> = this._onDidHighlight.event;
|
||||
private _onDidSelect = new Emitter<_.ISelectionEvent>();
|
||||
readonly onDidSelect: Event<_.ISelectionEvent> = this._onDidSelect.event;
|
||||
private _onDidFocus = new Emitter<_.IFocusEvent>();
|
||||
readonly onDidFocus: Event<_.IFocusEvent> = this._onDidFocus.event;
|
||||
|
||||
private _onDidRevealItem = new Relay<IItemRevealEvent>();
|
||||
readonly onDidRevealItem: Event<IItemRevealEvent> = this._onDidRevealItem.event;
|
||||
private _onExpandItem = new Relay<IItemExpandEvent>();
|
||||
readonly onExpandItem: Event<IItemExpandEvent> = this._onExpandItem.event;
|
||||
private _onDidExpandItem = new Relay<IItemExpandEvent>();
|
||||
readonly onDidExpandItem: Event<IItemExpandEvent> = this._onDidExpandItem.event;
|
||||
private _onCollapseItem = new Relay<IItemCollapseEvent>();
|
||||
readonly onCollapseItem: Event<IItemCollapseEvent> = this._onCollapseItem.event;
|
||||
private _onDidCollapseItem = new Relay<IItemCollapseEvent>();
|
||||
readonly onDidCollapseItem: Event<IItemCollapseEvent> = this._onDidCollapseItem.event;
|
||||
private _onDidAddTraitItem = new Relay<IItemTraitEvent>();
|
||||
readonly onDidAddTraitItem: Event<IItemTraitEvent> = this._onDidAddTraitItem.event;
|
||||
private _onDidRemoveTraitItem = new Relay<IItemCollapseEvent>();
|
||||
readonly onDidRemoveTraitItem: Event<IItemCollapseEvent> = this._onDidRemoveTraitItem.event;
|
||||
private _onDidRefreshItem = new Relay<Item>();
|
||||
readonly onDidRefreshItem: Event<Item> = this._onDidRefreshItem.event;
|
||||
private _onRefreshItemChildren = new Relay<IItemChildrenRefreshEvent>();
|
||||
readonly onRefreshItemChildren: Event<IItemChildrenRefreshEvent> = this._onRefreshItemChildren.event;
|
||||
private _onDidRefreshItemChildren = new Relay<IItemChildrenRefreshEvent>();
|
||||
readonly onDidRefreshItemChildren: Event<IItemChildrenRefreshEvent> = this._onDidRefreshItemChildren.event;
|
||||
private _onDidDisposeItem = new Relay<Item>();
|
||||
readonly onDidDisposeItem: Event<Item> = this._onDidDisposeItem.event;
|
||||
|
||||
constructor(context: _.ITreeContext) {
|
||||
this.context = context;
|
||||
this.input = null;
|
||||
this.traitsToItems = {};
|
||||
@@ -791,7 +925,7 @@ export class TreeModel extends Events.EventEmitter {
|
||||
|
||||
public setInput(element: any): WinJS.Promise {
|
||||
var eventData: IInputEvent = { item: this.input };
|
||||
this.emit('clearingInput', eventData);
|
||||
this._onSetInput.fire(eventData);
|
||||
|
||||
this.setSelection([]);
|
||||
this.setFocus();
|
||||
@@ -810,18 +944,25 @@ export class TreeModel extends Events.EventEmitter {
|
||||
|
||||
this.registry = new ItemRegistry();
|
||||
|
||||
this.registryDisposable = combinedDisposable([
|
||||
this.addEmitter(this.registry),
|
||||
this.registry.addListener('item:dispose', (event: IItemDisposeEvent) => {
|
||||
event.item.getAllTraits()
|
||||
.forEach(trait => delete this.traitsToItems[trait][event.item.id]);
|
||||
})
|
||||
]);
|
||||
this._onDidRevealItem.input = this.registry.onDidRevealItem;
|
||||
this._onExpandItem.input = this.registry.onExpandItem;
|
||||
this._onDidExpandItem.input = this.registry.onDidExpandItem;
|
||||
this._onCollapseItem.input = this.registry.onCollapseItem;
|
||||
this._onDidCollapseItem.input = this.registry.onDidCollapseItem;
|
||||
this._onDidAddTraitItem.input = this.registry.onDidAddTraitItem;
|
||||
this._onDidRemoveTraitItem.input = this.registry.onDidRemoveTraitItem;
|
||||
this._onDidRefreshItem.input = this.registry.onDidRefreshItem;
|
||||
this._onRefreshItemChildren.input = this.registry.onRefreshItemChildren;
|
||||
this._onDidRefreshItemChildren.input = this.registry.onDidRefreshItemChildren;
|
||||
this._onDidDisposeItem.input = this.registry.onDidDisposeItem;
|
||||
|
||||
this.registryDisposable = this.registry
|
||||
.onDidDisposeItem(item => item.getAllTraits().forEach(trait => delete this.traitsToItems[trait][item.id]));
|
||||
|
||||
var id = this.context.dataSource.getId(this.context.tree, element);
|
||||
this.input = new RootItem(id, this.registry, this.context, this.lock, element);
|
||||
eventData = { item: this.input };
|
||||
this.emit('setInput', eventData);
|
||||
this._onDidSetInput.fire(eventData);
|
||||
return this.refresh(this.input);
|
||||
}
|
||||
|
||||
@@ -837,9 +978,9 @@ export class TreeModel extends Events.EventEmitter {
|
||||
}
|
||||
|
||||
var eventData: IRefreshEvent = { item: item, recursive: recursive };
|
||||
this.emit('refreshing', eventData);
|
||||
this._onRefresh.fire(eventData);
|
||||
return item.refresh(recursive).then(() => {
|
||||
this.emit('refreshed', eventData);
|
||||
this._onDidRefresh.fire(eventData);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -894,6 +1035,27 @@ export class TreeModel extends Events.EventEmitter {
|
||||
return WinJS.Promise.join(promises);
|
||||
}
|
||||
|
||||
public collapseDeepestExpandedLevel(): WinJS.Promise {
|
||||
var levelToCollapse = this.findDeepestExpandedLevel(this.input, 0);
|
||||
|
||||
var items = [this.input];
|
||||
for (var i = 0; i < levelToCollapse; i++) {
|
||||
items = arrays.flatten(items.map(node => node.getChildren()));
|
||||
}
|
||||
|
||||
var promises = items.map(child => this.collapse(child, false));
|
||||
return WinJS.Promise.join(promises);
|
||||
}
|
||||
|
||||
private findDeepestExpandedLevel(item: Item, currentLevel: number): number {
|
||||
var expandedChildren = item.getChildren().filter(child => child.isExpanded());
|
||||
if (!expandedChildren.length) {
|
||||
return currentLevel;
|
||||
}
|
||||
|
||||
return Math.max(...expandedChildren.map(child => this.findDeepestExpandedLevel(child, currentLevel + 1)));
|
||||
}
|
||||
|
||||
public toggleExpansion(element: any, recursive: boolean = false): WinJS.Promise {
|
||||
return this.isExpanded(element) ? this.collapse(element, recursive) : this.expand(element);
|
||||
}
|
||||
@@ -964,7 +1126,7 @@ export class TreeModel extends Events.EventEmitter {
|
||||
public setHighlight(element?: any, eventPayload?: any): void {
|
||||
this.setTraits('highlighted', element ? [element] : []);
|
||||
var eventData: _.IHighlightEvent = { highlight: this.getHighlight(), payload: eventPayload };
|
||||
this.emit('highlight', eventData);
|
||||
this._onDidHighlight.fire(eventData);
|
||||
}
|
||||
|
||||
public getHighlight(includeHidden?: boolean): any {
|
||||
@@ -1011,7 +1173,7 @@ export class TreeModel extends Events.EventEmitter {
|
||||
public selectAll(elements: any[], eventPayload?: any): void {
|
||||
this.addTraits('selected', elements);
|
||||
var eventData: _.ISelectionEvent = { selection: this.getSelection(), payload: eventPayload };
|
||||
this.emit('selection', eventData);
|
||||
this._onDidSelect.fire(eventData);
|
||||
}
|
||||
|
||||
public deselect(element: any, eventPayload?: any): void {
|
||||
@@ -1021,19 +1183,19 @@ export class TreeModel extends Events.EventEmitter {
|
||||
public deselectAll(elements: any[], eventPayload?: any): void {
|
||||
this.removeTraits('selected', elements);
|
||||
var eventData: _.ISelectionEvent = { selection: this.getSelection(), payload: eventPayload };
|
||||
this.emit('selection', eventData);
|
||||
this._onDidSelect.fire(eventData);
|
||||
}
|
||||
|
||||
public setSelection(elements: any[], eventPayload?: any): void {
|
||||
this.setTraits('selected', elements);
|
||||
var eventData: _.ISelectionEvent = { selection: this.getSelection(), payload: eventPayload };
|
||||
this.emit('selection', eventData);
|
||||
this._onDidSelect.fire(eventData);
|
||||
}
|
||||
|
||||
public toggleSelection(element: any, eventPayload?: any): void {
|
||||
this.toggleTrait('selected', element);
|
||||
var eventData: _.ISelectionEvent = { selection: this.getSelection(), payload: eventPayload };
|
||||
this.emit('selection', eventData);
|
||||
this._onDidSelect.fire(eventData);
|
||||
}
|
||||
|
||||
public isSelected(element: any): boolean {
|
||||
@@ -1077,7 +1239,7 @@ export class TreeModel extends Events.EventEmitter {
|
||||
previousItem: Item = null;
|
||||
|
||||
if (selection.length === 0) {
|
||||
var nav = this.getNavigator(this.input);
|
||||
let nav = this.getNavigator(this.input);
|
||||
|
||||
while (item = nav.next()) {
|
||||
previousItem = item;
|
||||
@@ -1087,7 +1249,7 @@ export class TreeModel extends Events.EventEmitter {
|
||||
|
||||
} else {
|
||||
item = selection[0];
|
||||
var nav = this.getNavigator(item, false);
|
||||
let nav = this.getNavigator(item, false);
|
||||
|
||||
for (var i = 0; i < count; i++) {
|
||||
previousItem = nav.previous();
|
||||
@@ -1123,7 +1285,7 @@ export class TreeModel extends Events.EventEmitter {
|
||||
public setFocus(element?: any, eventPayload?: any): void {
|
||||
this.setTraits('focused', element ? [element] : []);
|
||||
var eventData: _.IFocusEvent = { focus: this.getFocus(), payload: eventPayload };
|
||||
this.emit('focus', eventData);
|
||||
this._onDidFocus.fire(eventData);
|
||||
}
|
||||
|
||||
public isFocused(element: any): boolean {
|
||||
@@ -1320,7 +1482,7 @@ export class TreeModel extends Events.EventEmitter {
|
||||
var items: { [id: string]: Item; } = {};
|
||||
var item: Item;
|
||||
|
||||
for (var i = 0, len = elements.length; i < len; i++) {
|
||||
for (let i = 0, len = elements.length; i < len; i++) {
|
||||
item = this.getItem(elements[i]);
|
||||
|
||||
if (item) {
|
||||
@@ -1342,7 +1504,7 @@ export class TreeModel extends Events.EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0, len = itemsToRemoveTrait.length; i < len; i++) {
|
||||
for (let i = 0, len = itemsToRemoveTrait.length; i < len; i++) {
|
||||
item = itemsToRemoveTrait[i];
|
||||
item.removeTrait(trait);
|
||||
delete traitItems[item.id];
|
||||
@@ -1378,6 +1540,23 @@ export class TreeModel extends Events.EventEmitter {
|
||||
this.registry = null;
|
||||
}
|
||||
|
||||
super.dispose();
|
||||
this._onSetInput.dispose();
|
||||
this._onDidSetInput.dispose();
|
||||
this._onRefresh.dispose();
|
||||
this._onDidRefresh.dispose();
|
||||
this._onDidHighlight.dispose();
|
||||
this._onDidSelect.dispose();
|
||||
this._onDidFocus.dispose();
|
||||
this._onDidRevealItem.dispose();
|
||||
this._onExpandItem.dispose();
|
||||
this._onDidExpandItem.dispose();
|
||||
this._onCollapseItem.dispose();
|
||||
this._onDidCollapseItem.dispose();
|
||||
this._onDidAddTraitItem.dispose();
|
||||
this._onDidRemoveTraitItem.dispose();
|
||||
this._onDidRefreshItem.dispose();
|
||||
this._onRefreshItemChildren.dispose();
|
||||
this._onDidRefreshItemChildren.dispose();
|
||||
this._onDidDisposeItem.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import { HeightMap, IViewItem } from 'vs/base/parts/tree/browser/treeViewModel';
|
||||
import _ = require('vs/base/parts/tree/browser/tree');
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { EmitterEvent } from 'vs/base/common/eventEmitter';
|
||||
import { IDomNodePagePosition } from 'vs/base/browser/dom';
|
||||
|
||||
export interface IRow {
|
||||
element: HTMLElement;
|
||||
@@ -379,7 +379,6 @@ export class TreeView extends HeightMap {
|
||||
private styleElement: HTMLStyleElement;
|
||||
private rowsContainer: HTMLElement;
|
||||
private scrollableElement: ScrollableElement;
|
||||
private wrapperGesture: Touch.Gesture;
|
||||
private msGesture: MSGesture;
|
||||
private lastPointerType: string;
|
||||
private lastClickTimeStamp: number = 0;
|
||||
@@ -392,8 +391,6 @@ export class TreeView extends HeightMap {
|
||||
|
||||
private isRefreshing = false;
|
||||
private refreshingPreviousChildrenIds: { [id: string]: string[] } = {};
|
||||
|
||||
private dragAndDropListeners: { (): void; }[];
|
||||
private currentDragAndDropData: _.IDragAndDropData;
|
||||
private currentDropElement: any;
|
||||
private currentDropElementReaction: _.IDragOverReaction;
|
||||
@@ -437,7 +434,6 @@ export class TreeView extends HeightMap {
|
||||
|
||||
this.modelListeners = [];
|
||||
this.viewListeners = [];
|
||||
this.dragAndDropListeners = [];
|
||||
|
||||
this.model = null;
|
||||
this.items = {};
|
||||
@@ -473,14 +469,13 @@ export class TreeView extends HeightMap {
|
||||
});
|
||||
this.scrollableElement.onScroll((e) => {
|
||||
this.render(e.scrollTop, e.height);
|
||||
this.emit('scroll', e); // TODO@Joao: is anyone interested in this event?
|
||||
});
|
||||
|
||||
if (Browser.isIE) {
|
||||
this.wrapper.style.msTouchAction = 'none';
|
||||
this.wrapper.style.msContentZooming = 'none';
|
||||
} else {
|
||||
this.wrapperGesture = new Touch.Gesture(this.wrapper);
|
||||
Touch.Gesture.addTarget(this.wrapper);
|
||||
}
|
||||
|
||||
this.rowsContainer = document.createElement('div');
|
||||
@@ -490,8 +485,8 @@ export class TreeView extends HeightMap {
|
||||
}
|
||||
|
||||
var focusTracker = DOM.trackFocus(this.domNode);
|
||||
focusTracker.addFocusListener(() => this.onFocus());
|
||||
focusTracker.addBlurListener(() => this.onBlur());
|
||||
this.viewListeners.push(focusTracker.onDidFocus(() => this.onFocus()));
|
||||
this.viewListeners.push(focusTracker.onDidBlur(() => this.onBlur()));
|
||||
this.viewListeners.push(focusTracker);
|
||||
|
||||
this.viewListeners.push(DOM.addDisposableListener(this.domNode, 'keydown', (e) => this.onKeyDown(e)));
|
||||
@@ -718,65 +713,21 @@ export class TreeView extends HeightMap {
|
||||
this.releaseModel();
|
||||
this.model = newModel;
|
||||
|
||||
this.modelListeners.push(this.model.addBulkListener((e) => this.onModelEvents(e)));
|
||||
}
|
||||
this.model.onRefresh(this.onRefreshing, this, this.modelListeners);
|
||||
this.model.onDidRefresh(this.onRefreshed, this, this.modelListeners);
|
||||
this.model.onSetInput(this.onClearingInput, this, this.modelListeners);
|
||||
this.model.onDidSetInput(this.onSetInput, this, this.modelListeners);
|
||||
this.model.onDidFocus(this.onModelFocusChange, this, this.modelListeners);
|
||||
|
||||
private onModelEvents(events: EmitterEvent[]): void {
|
||||
var elementsToRefresh: Model.Item[] = [];
|
||||
|
||||
for (var i = 0, len = events.length; i < len; i++) {
|
||||
var event = events[i];
|
||||
var data = event.data;
|
||||
|
||||
switch (event.type) {
|
||||
case 'refreshing':
|
||||
this.onRefreshing();
|
||||
break;
|
||||
case 'refreshed':
|
||||
this.onRefreshed();
|
||||
break;
|
||||
case 'clearingInput':
|
||||
this.onClearingInput(data);
|
||||
break;
|
||||
case 'setInput':
|
||||
this.onSetInput(data);
|
||||
break;
|
||||
case 'item:childrenRefreshing':
|
||||
this.onItemChildrenRefreshing(data);
|
||||
break;
|
||||
case 'item:childrenRefreshed':
|
||||
this.onItemChildrenRefreshed(data);
|
||||
break;
|
||||
case 'item:refresh':
|
||||
elementsToRefresh.push(data.item);
|
||||
break;
|
||||
case 'item:expanding':
|
||||
this.onItemExpanding(data);
|
||||
break;
|
||||
case 'item:expanded':
|
||||
this.onItemExpanded(data);
|
||||
break;
|
||||
case 'item:collapsing':
|
||||
this.onItemCollapsing(data);
|
||||
break;
|
||||
case 'item:reveal':
|
||||
this.onItemReveal(data);
|
||||
break;
|
||||
case 'item:addTrait':
|
||||
this.onItemAddTrait(data);
|
||||
break;
|
||||
case 'item:removeTrait':
|
||||
this.onItemRemoveTrait(data);
|
||||
break;
|
||||
case 'focus':
|
||||
this.onModelFocusChange();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (elementsToRefresh.length > 0) {
|
||||
this.onItemsRefresh(elementsToRefresh);
|
||||
}
|
||||
this.model.onRefreshItemChildren(this.onItemChildrenRefreshing, this, this.modelListeners);
|
||||
this.model.onDidRefreshItemChildren(this.onItemChildrenRefreshed, this, this.modelListeners);
|
||||
this.model.onDidRefreshItem(this.onItemRefresh, this, this.modelListeners);
|
||||
this.model.onExpandItem(this.onItemExpanding, this, this.modelListeners);
|
||||
this.model.onDidExpandItem(this.onItemExpanded, this, this.modelListeners);
|
||||
this.model.onCollapseItem(this.onItemCollapsing, this, this.modelListeners);
|
||||
this.model.onDidRevealItem(this.onItemReveal, this, this.modelListeners);
|
||||
this.model.onDidAddTraitItem(this.onItemAddTrait, this, this.modelListeners);
|
||||
this.model.onDidRemoveTraitItem(this.onItemRemoveTrait, this, this.modelListeners);
|
||||
}
|
||||
|
||||
private onRefreshing(): void {
|
||||
@@ -895,7 +846,6 @@ export class TreeView extends HeightMap {
|
||||
private onSetInput(e: Model.IInputEvent): void {
|
||||
this.context.cache.garbageCollect();
|
||||
this.inputItem = new RootViewItem(this.context, <Model.Item>e.item, this.wrapper);
|
||||
this.emit('viewItem:create', { item: this.inputItem.model });
|
||||
}
|
||||
|
||||
private onItemChildrenRefreshing(e: Model.IItemChildrenRefreshEvent): void {
|
||||
@@ -1005,6 +955,10 @@ export class TreeView extends HeightMap {
|
||||
}
|
||||
}
|
||||
|
||||
private onItemRefresh(item: Model.Item): void {
|
||||
this.onItemsRefresh([item]);
|
||||
}
|
||||
|
||||
private onItemsRefresh(items: Model.Item[]): void {
|
||||
this.onRefreshItemSet(items.filter(item => this.items.hasOwnProperty(item.id)));
|
||||
this.onRowsChanged();
|
||||
@@ -1146,10 +1100,7 @@ export class TreeView extends HeightMap {
|
||||
|
||||
public onRemoveItem(item: ViewItem): void {
|
||||
this.removeItemFromDOM(item);
|
||||
|
||||
item.dispose();
|
||||
this.emit('viewItem:dispose', { item: this.inputItem.model });
|
||||
|
||||
delete this.items[item.id];
|
||||
}
|
||||
|
||||
@@ -1270,13 +1221,16 @@ export class TreeView extends HeightMap {
|
||||
var keyboardEvent = new Keyboard.StandardKeyboardEvent(<KeyboardEvent>event);
|
||||
element = this.model.getFocus();
|
||||
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
var position: IDomNodePagePosition;
|
||||
|
||||
var id = this.context.dataSource.getId(this.context.tree, element);
|
||||
var viewItem = this.items[id];
|
||||
var position = DOM.getDomNodePagePosition(viewItem.element);
|
||||
if (!element) {
|
||||
element = this.model.getInput();
|
||||
position = DOM.getDomNodePagePosition(this.inputItem.element);
|
||||
} else {
|
||||
var id = this.context.dataSource.getId(this.context.tree, element);
|
||||
var viewItem = this.items[id];
|
||||
position = DOM.getDomNodePagePosition(viewItem.element);
|
||||
}
|
||||
|
||||
resultEvent = new _.KeyboardContextMenuEvent(position.left + position.width, position.top, keyboardEvent);
|
||||
|
||||
@@ -1697,11 +1651,6 @@ export class TreeView extends HeightMap {
|
||||
}
|
||||
this.domNode = null;
|
||||
|
||||
if (this.wrapperGesture) {
|
||||
this.wrapperGesture.dispose();
|
||||
this.wrapperGesture = null;
|
||||
}
|
||||
|
||||
if (this.context.cache) {
|
||||
this.context.cache.dispose();
|
||||
this.context.cache = null;
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { EventEmitter } from 'vs/base/common/eventEmitter';
|
||||
import { INextIterator, ArrayIterator } from 'vs/base/common/iterator';
|
||||
import { Item } from './treeModel';
|
||||
|
||||
@@ -13,14 +12,12 @@ export interface IViewItem {
|
||||
height: number;
|
||||
}
|
||||
|
||||
export class HeightMap extends EventEmitter {
|
||||
export class HeightMap {
|
||||
|
||||
private heightMap: IViewItem[];
|
||||
private indexes: { [item: string]: number; };
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.heightMap = [];
|
||||
this.indexes = {};
|
||||
}
|
||||
@@ -59,7 +56,6 @@ export class HeightMap extends EventEmitter {
|
||||
while (item = iterator.next()) {
|
||||
viewItem = this.createViewItem(item);
|
||||
viewItem.top = totalSize + sizeDiff;
|
||||
this.emit('viewItem:create', { item: viewItem.model });
|
||||
|
||||
this.indexes[item.id] = i++;
|
||||
itemsToInsert.push(viewItem);
|
||||
|
||||
@@ -9,9 +9,9 @@ import assert = require('assert');
|
||||
import lifecycle = require('vs/base/common/lifecycle');
|
||||
import _ = require('vs/base/parts/tree/browser/tree');
|
||||
import WinJS = require('vs/base/common/winjs.base');
|
||||
import Events = require('vs/base/common/eventEmitter');
|
||||
import model = require('vs/base/parts/tree/browser/treeModel');
|
||||
import TreeDefaults = require('vs/base/parts/tree/browser/treeDefaults');
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
|
||||
export class FakeRenderer {
|
||||
|
||||
@@ -74,11 +74,11 @@ class EventCounter {
|
||||
this._count = 0;
|
||||
}
|
||||
|
||||
public listen(emitter: Events.IEventEmitter, event: string, fn: (e) => void = null): () => void {
|
||||
let r = emitter.addListener(event, (e) => {
|
||||
public listen<T>(event: Event<T>, fn: (e: T) => void = null): () => void {
|
||||
let r = event(data => {
|
||||
this._count++;
|
||||
if (fn) {
|
||||
fn(e);
|
||||
fn(data);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -203,11 +203,11 @@ suite('TreeModel', () => {
|
||||
|
||||
test('refresh() refreshes all', (done) => {
|
||||
model.setInput(SAMPLE.AB).then(() => {
|
||||
counter.listen(model, 'refreshing'); // 1
|
||||
counter.listen(model, 'refreshed'); // 1
|
||||
counter.listen(model, 'item:refresh'); // 4
|
||||
counter.listen(model, 'item:childrenRefreshing'); // 1
|
||||
counter.listen(model, 'item:childrenRefreshed'); // 1
|
||||
counter.listen(model.onRefresh); // 1
|
||||
counter.listen(model.onDidRefresh); // 1
|
||||
counter.listen(model.onDidRefreshItem); // 4
|
||||
counter.listen(model.onRefreshItemChildren); // 1
|
||||
counter.listen(model.onDidRefreshItemChildren); // 1
|
||||
return model.refresh(null);
|
||||
}).done(() => {
|
||||
assert.equal(counter.count, 8);
|
||||
@@ -217,11 +217,11 @@ suite('TreeModel', () => {
|
||||
|
||||
test('refresh(root) refreshes all', (done) => {
|
||||
model.setInput(SAMPLE.AB).then(() => {
|
||||
counter.listen(model, 'refreshing'); // 1
|
||||
counter.listen(model, 'refreshed'); // 1
|
||||
counter.listen(model, 'item:refresh'); // 4
|
||||
counter.listen(model, 'item:childrenRefreshing'); // 1
|
||||
counter.listen(model, 'item:childrenRefreshed'); // 1
|
||||
counter.listen(model.onRefresh); // 1
|
||||
counter.listen(model.onDidRefresh); // 1
|
||||
counter.listen(model.onDidRefreshItem); // 4
|
||||
counter.listen(model.onRefreshItemChildren); // 1
|
||||
counter.listen(model.onDidRefreshItemChildren); // 1
|
||||
return model.refresh(SAMPLE.AB);
|
||||
}).done(() => {
|
||||
assert.equal(counter.count, 8);
|
||||
@@ -231,11 +231,11 @@ suite('TreeModel', () => {
|
||||
|
||||
test('refresh(root, false) refreshes the root', (done) => {
|
||||
model.setInput(SAMPLE.AB).then(() => {
|
||||
counter.listen(model, 'refreshing'); // 1
|
||||
counter.listen(model, 'refreshed'); // 1
|
||||
counter.listen(model, 'item:refresh'); // 1
|
||||
counter.listen(model, 'item:childrenRefreshing'); // 1
|
||||
counter.listen(model, 'item:childrenRefreshed'); // 1
|
||||
counter.listen(model.onRefresh); // 1
|
||||
counter.listen(model.onDidRefresh); // 1
|
||||
counter.listen(model.onDidRefreshItem); // 1
|
||||
counter.listen(model.onRefreshItemChildren); // 1
|
||||
counter.listen(model.onDidRefreshItemChildren); // 1
|
||||
return model.refresh(SAMPLE.AB, false);
|
||||
}).done(() => {
|
||||
assert.equal(counter.count, 5);
|
||||
@@ -245,11 +245,11 @@ suite('TreeModel', () => {
|
||||
|
||||
test('refresh(collapsed element) does not refresh descendants', (done) => {
|
||||
model.setInput(SAMPLE.AB).then(() => {
|
||||
counter.listen(model, 'refreshing'); // 1
|
||||
counter.listen(model, 'refreshed'); // 1
|
||||
counter.listen(model, 'item:refresh'); // 1
|
||||
counter.listen(model, 'item:childrenRefreshing'); // 0
|
||||
counter.listen(model, 'item:childrenRefreshed'); // 0
|
||||
counter.listen(model.onRefresh); // 1
|
||||
counter.listen(model.onDidRefresh); // 1
|
||||
counter.listen(model.onDidRefreshItem); // 1
|
||||
counter.listen(model.onRefreshItemChildren); // 0
|
||||
counter.listen(model.onDidRefreshItemChildren); // 0
|
||||
return model.refresh(SAMPLE.AB.children[0]);
|
||||
}).done(() => {
|
||||
assert.equal(counter.count, 3);
|
||||
@@ -261,11 +261,11 @@ suite('TreeModel', () => {
|
||||
model.setInput(SAMPLE.AB).then(() => {
|
||||
model.expand(SAMPLE.AB.children[0]);
|
||||
|
||||
counter.listen(model, 'refreshing'); // 1
|
||||
counter.listen(model, 'refreshed'); // 1
|
||||
counter.listen(model, 'item:refresh'); // 3
|
||||
counter.listen(model, 'item:childrenRefreshing'); // 1
|
||||
counter.listen(model, 'item:childrenRefreshed'); // 1
|
||||
counter.listen(model.onRefresh); // 1
|
||||
counter.listen(model.onDidRefresh); // 1
|
||||
counter.listen(model.onDidRefreshItem); // 3
|
||||
counter.listen(model.onRefreshItemChildren); // 1
|
||||
counter.listen(model.onDidRefreshItemChildren); // 1
|
||||
return model.refresh(SAMPLE.AB.children[0]);
|
||||
}).done(() => {
|
||||
assert.equal(counter.count, 7);
|
||||
@@ -277,14 +277,14 @@ suite('TreeModel', () => {
|
||||
model.setInput(SAMPLE.AB).then(() => {
|
||||
model.expand(SAMPLE.AB.children[0]);
|
||||
|
||||
counter.listen(model, 'refreshing'); // 1
|
||||
counter.listen(model, 'refreshed'); // 1
|
||||
counter.listen(model, 'item:refresh', (e) => { // 1
|
||||
assert.equal(e.item.id, 'a');
|
||||
counter.listen(model.onRefresh); // 1
|
||||
counter.listen(model.onDidRefresh); // 1
|
||||
counter.listen(model.onDidRefreshItem, item => { // 1
|
||||
assert.equal(item.id, 'a');
|
||||
counter.up();
|
||||
});
|
||||
counter.listen(model, 'item:childrenRefreshing'); // 1
|
||||
counter.listen(model, 'item:childrenRefreshed'); // 1
|
||||
counter.listen(model.onRefreshItemChildren); // 1
|
||||
counter.listen(model.onDidRefreshItemChildren); // 1
|
||||
return model.refresh(SAMPLE.AB.children[0], false);
|
||||
}).done(() => {
|
||||
assert.equal(counter.count, 6);
|
||||
@@ -296,16 +296,16 @@ suite('TreeModel', () => {
|
||||
model.setInput(SAMPLE.AB).then(() => {
|
||||
model.expandAll(['a', 'c']);
|
||||
|
||||
counter.listen(model, 'item:refresh', (e) => {
|
||||
switch (e.item.id) {
|
||||
case 'ROOT': assert.equal(e.item.getDepth(), 0); break;
|
||||
case 'a': assert.equal(e.item.getDepth(), 1); break;
|
||||
case 'aa': assert.equal(e.item.getDepth(), 2); break;
|
||||
case 'ab': assert.equal(e.item.getDepth(), 2); break;
|
||||
case 'b': assert.equal(e.item.getDepth(), 1); break;
|
||||
case 'c': assert.equal(e.item.getDepth(), 1); break;
|
||||
case 'ca': assert.equal(e.item.getDepth(), 2); break;
|
||||
case 'cb': assert.equal(e.item.getDepth(), 2); break;
|
||||
counter.listen(model.onDidRefreshItem, item => {
|
||||
switch (item.id) {
|
||||
case 'ROOT': assert.equal(item.getDepth(), 0); break;
|
||||
case 'a': assert.equal(item.getDepth(), 1); break;
|
||||
case 'aa': assert.equal(item.getDepth(), 2); break;
|
||||
case 'ab': assert.equal(item.getDepth(), 2); break;
|
||||
case 'b': assert.equal(item.getDepth(), 1); break;
|
||||
case 'c': assert.equal(item.getDepth(), 1); break;
|
||||
case 'ca': assert.equal(item.getDepth(), 2); break;
|
||||
case 'cb': assert.equal(item.getDepth(), 2); break;
|
||||
default: return;
|
||||
}
|
||||
counter.up();
|
||||
@@ -548,13 +548,13 @@ suite('TreeModel - Expansion', () => {
|
||||
|
||||
test('collapse, expand', (done) => {
|
||||
model.setInput(SAMPLE.AB).done(() => {
|
||||
counter.listen(model, 'item:expanding', (e) => {
|
||||
counter.listen(model.onExpandItem, (e) => {
|
||||
assert.equal(e.item.id, 'a');
|
||||
var nav = model.getNavigator(e.item);
|
||||
assert.equal(nav.next() && false, null);
|
||||
});
|
||||
|
||||
counter.listen(model, 'item:expanded', (e) => {
|
||||
counter.listen(model.onDidExpandItem, (e) => {
|
||||
assert.equal(e.item.id, 'a');
|
||||
var nav = model.getNavigator(e.item);
|
||||
assert.equal(nav.next().id, 'aa');
|
||||
@@ -635,6 +635,24 @@ suite('TreeModel - Expansion', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('collapseDeepestExpandedLevel', (done) => {
|
||||
model.setInput(SAMPLE.DEEP2).done(() => {
|
||||
model.expand(SAMPLE.DEEP2.children[0]).done(() => {
|
||||
model.expand(SAMPLE.DEEP2.children[0].children[0]).done(() => {
|
||||
|
||||
assert(model.isExpanded(SAMPLE.DEEP2.children[0]));
|
||||
assert(model.isExpanded(SAMPLE.DEEP2.children[0].children[0]));
|
||||
|
||||
model.collapseDeepestExpandedLevel().done(() => {
|
||||
assert(model.isExpanded(SAMPLE.DEEP2.children[0]));
|
||||
assert(!model.isExpanded(SAMPLE.DEEP2.children[0].children[0]));
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('auto expand single child folders', (done) => {
|
||||
model.setInput(SAMPLE.DEEP).done(() => {
|
||||
model.expand(SAMPLE.DEEP.children[0]).done(() => {
|
||||
@@ -657,12 +675,12 @@ suite('TreeModel - Expansion', () => {
|
||||
assert.equal(nav.next().id, 'c');
|
||||
assert.equal(nav.next() && false, null);
|
||||
|
||||
var f: () => void = counter.listen(model, 'item:childrenRefreshing', (e) => {
|
||||
var f: () => void = counter.listen(model.onRefreshItemChildren, (e) => {
|
||||
assert.equal(e.item.id, 'a');
|
||||
f();
|
||||
});
|
||||
|
||||
var g: () => void = counter.listen(model, 'item:childrenRefreshed', (e) => {
|
||||
var g: () => void = counter.listen(model.onDidRefreshItemChildren, (e) => {
|
||||
assert.equal(e.item.id, 'a');
|
||||
g();
|
||||
});
|
||||
@@ -1120,13 +1138,18 @@ suite('TreeModel - Traits', () => {
|
||||
});
|
||||
});
|
||||
|
||||
class DynamicModel extends Events.EventEmitter implements _.IDataSource {
|
||||
class DynamicModel implements _.IDataSource {
|
||||
|
||||
private data: any;
|
||||
public promiseFactory: { (): WinJS.Promise; };
|
||||
|
||||
private _onGetChildren = new Emitter<any>();
|
||||
readonly onGetChildren: Event<any> = this._onGetChildren.event;
|
||||
|
||||
private _onDidGetChildren = new Emitter<any>();
|
||||
readonly onDidGetChildren: Event<any> = this._onDidGetChildren.event;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.data = { root: [] };
|
||||
this.promiseFactory = null;
|
||||
}
|
||||
@@ -1164,10 +1187,10 @@ class DynamicModel extends Events.EventEmitter implements _.IDataSource {
|
||||
}
|
||||
|
||||
public getChildren(tree, element): WinJS.Promise {
|
||||
this.emit('getChildren', element);
|
||||
this._onGetChildren.fire(element);
|
||||
var result = this.promiseFactory ? this.promiseFactory() : WinJS.TPromise.as(null);
|
||||
return result.then(() => {
|
||||
this.emit('gotChildren', element);
|
||||
this._onDidGetChildren.fire(element);
|
||||
return WinJS.TPromise.as(this.data[element]);
|
||||
});
|
||||
}
|
||||
@@ -1208,8 +1231,8 @@ suite('TreeModel - Dynamic data model', () => {
|
||||
|
||||
var items = ['baby', 'son', 'daughter', 'father'];
|
||||
var times = 0;
|
||||
counter.listen(model, 'item:dispose', (e) => {
|
||||
assert.equal(items[times++], e.item.id);
|
||||
counter.listen(model.onDidDisposeItem, item => {
|
||||
assert.equal(items[times++], item.id);
|
||||
});
|
||||
|
||||
model.refresh().done(() => {
|
||||
@@ -1320,7 +1343,7 @@ suite('TreeModel - Dynamic data model', () => {
|
||||
model.collapse('father');
|
||||
|
||||
var times = 0;
|
||||
var listener = dataModel.addListener('getChildren', (element) => {
|
||||
var listener = dataModel.onGetChildren((element) => {
|
||||
times++;
|
||||
assert.equal(element, 'grandfather');
|
||||
});
|
||||
@@ -1329,7 +1352,7 @@ suite('TreeModel - Dynamic data model', () => {
|
||||
assert.equal(times, 1);
|
||||
listener.dispose();
|
||||
|
||||
listener = dataModel.addListener('getChildren', (element) => {
|
||||
listener = dataModel.onGetChildren((element) => {
|
||||
times++;
|
||||
assert.equal(element, 'father');
|
||||
});
|
||||
@@ -1369,8 +1392,8 @@ suite('TreeModel - Dynamic data model', () => {
|
||||
|
||||
var getTimes = 0;
|
||||
var gotTimes = 0;
|
||||
var getListener = dataModel.addListener('getChildren', (element) => { getTimes++; });
|
||||
var gotListener = dataModel.addListener('gotChildren', (element) => { gotTimes++; });
|
||||
var getListener = dataModel.onGetChildren((element) => { getTimes++; });
|
||||
var gotListener = dataModel.onDidGetChildren((element) => { gotTimes++; });
|
||||
|
||||
var p1 = model.refresh('father');
|
||||
assert.equal(getTimes, 1);
|
||||
@@ -1414,20 +1437,18 @@ suite('TreeModel - Dynamic data model', () => {
|
||||
assert.equal(nav.next() && false, null);
|
||||
|
||||
var refreshTimes = 0;
|
||||
counter.listen(model, 'item:refresh', (e) => { refreshTimes++; });
|
||||
counter.listen(model.onDidRefreshItem, (e) => { refreshTimes++; });
|
||||
|
||||
var getTimes = 0;
|
||||
var getListener = dataModel.addListener('getChildren', (element) => { getTimes++; });
|
||||
var getListener = dataModel.onGetChildren((element) => { getTimes++; });
|
||||
|
||||
var gotTimes = 0;
|
||||
var gotListener = dataModel.addListener('gotChildren', (element) => { gotTimes++; });
|
||||
|
||||
var p1, p2;
|
||||
var gotListener = dataModel.onDidGetChildren((element) => { gotTimes++; });
|
||||
|
||||
var p1Completes = [];
|
||||
dataModel.promiseFactory = () => { return new WinJS.TPromise((c) => { p1Completes.push(c); }); };
|
||||
|
||||
p1 = model.refresh('grandfather');
|
||||
model.refresh('grandfather');
|
||||
|
||||
// just a single get
|
||||
assert.equal(refreshTimes, 1); // (+1) grandfather
|
||||
@@ -1444,7 +1465,7 @@ suite('TreeModel - Dynamic data model', () => {
|
||||
|
||||
var p2Complete;
|
||||
dataModel.promiseFactory = () => { return new WinJS.TPromise((c) => { p2Complete = c; }); };
|
||||
p2 = model.refresh('father');
|
||||
var p2 = model.refresh('father');
|
||||
|
||||
// same situation still
|
||||
assert.equal(refreshTimes, 3); // (+1) second father refresh
|
||||
@@ -1497,15 +1518,14 @@ suite('TreeModel - Dynamic data model', () => {
|
||||
|
||||
var getTimes = 0;
|
||||
var gotTimes = 0;
|
||||
var getListener = dataModel.addListener('getChildren', (element) => { getTimes++; });
|
||||
var gotListener = dataModel.addListener('gotChildren', (element) => { gotTimes++; });
|
||||
|
||||
var p1, p2;
|
||||
var getListener = dataModel.onGetChildren((element) => { getTimes++; });
|
||||
var gotListener = dataModel.onDidGetChildren((element) => { gotTimes++; });
|
||||
var p2;
|
||||
|
||||
var p1Complete;
|
||||
dataModel.promiseFactory = () => { return new WinJS.TPromise((c) => { p1Complete = c; }); };
|
||||
|
||||
p1 = model.refresh('father');
|
||||
model.refresh('father');
|
||||
|
||||
assert.equal(getTimes, 1);
|
||||
assert.equal(gotTimes, 0);
|
||||
@@ -1695,8 +1715,8 @@ suite('TreeModel - bugs', () => {
|
||||
var getBartChildren = getGetBartChildren(0);
|
||||
|
||||
// item expanding should not exist!
|
||||
counter.listen(model, 'item:expanding', () => { assert(false, 'should never receive item:expanding event'); });
|
||||
counter.listen(model, 'item:expanded', () => { assert(false, 'should never receive item:expanded event'); });
|
||||
counter.listen(model.onExpandItem, () => { assert(false, 'should never receive item:expanding event'); });
|
||||
counter.listen(model.onDidExpandItem, () => { assert(false, 'should never receive item:expanded event'); });
|
||||
|
||||
model.setInput('root').then(() => {
|
||||
|
||||
@@ -1723,7 +1743,7 @@ suite('TreeModel - bugs', () => {
|
||||
}).done(() => {
|
||||
|
||||
// teardown
|
||||
while (listeners.length > 0) { listeners.pop()(); };
|
||||
while (listeners.length > 0) { listeners.pop()(); }
|
||||
listeners = null;
|
||||
model.dispose();
|
||||
model = null;
|
||||
|
||||
Reference in New Issue
Block a user