Skip to content

Commit

Permalink
Tree decorators infrastructure created
Browse files Browse the repository at this point in the history
A first example is also included: gitStatusTreeDecorator

Resolves #5866
Related #211
  • Loading branch information
kisstkondoros committed Jul 3, 2016
1 parent 4e72dcc commit b47ebd3
Show file tree
Hide file tree
Showing 12 changed files with 308 additions and 12 deletions.
13 changes: 13 additions & 0 deletions src/vs/base/parts/tree/browser/tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ import Keyboard = require('vs/base/browser/keyboardEvent');
import { INavigator } from 'vs/base/common/iterator';
import { ScrollbarVisibility } from 'vs/base/browser/ui/scrollbar/scrollableElementOptions';

export interface IRow {
element: HTMLElement;
templateId: string;
templateData: any;
}

export interface ITree extends Events.IEventEmitter {

emit(eventType:string, data?:any):void;
Expand Down Expand Up @@ -355,6 +361,12 @@ export interface IDataSource {
getParent(tree: ITree, element: any): WinJS.Promise;
}

export interface IDecorator {
onActivate(tree: ITree): void;
decorate(tree: ITree, element: any, templateId: string, row: IRow): void;
dispose(): void;
}

export interface IRenderer {

/**
Expand Down Expand Up @@ -614,6 +626,7 @@ export interface IHighlightEvent {
export interface ITreeConfiguration {
dataSource: IDataSource;
renderer?: IRenderer;
decorator?: IDecorator;
controller?: IController;
dnd?: IDragAndDrop;
filter?: IFilter;
Expand Down
9 changes: 9 additions & 0 deletions src/vs/base/parts/tree/browser/treeImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export class TreeContext implements _.ITreeContext {
public dataSource:_.IDataSource;
public renderer:_.IRenderer;
public controller:_.IController;
public decorator:_.IDecorator;
public dnd:_.IDragAndDrop;
public filter:_.IFilter;
public sorter:_.ISorter;
Expand All @@ -42,7 +43,12 @@ export class TreeContext implements _.ITreeContext {
this.dnd = configuration.dnd || new TreeDefaults.DefaultDragAndDrop();
this.filter = configuration.filter || new TreeDefaults.DefaultFilter();
this.sorter = configuration.sorter || null;
this.decorator = configuration.decorator || null;
this.accessibilityProvider = configuration.accessibilityProvider || new TreeDefaults.DefaultAccessibilityProvider();

if (this.decorator) {
this.decorator.onActivate(tree);
}
}
}

Expand Down Expand Up @@ -327,6 +333,9 @@ export class Tree extends Events.EventEmitter implements _.ITree {
this.view.dispose();
this.view = null;
}
if (this.context.decorator !== null) {
this.context.decorator.dispose();
}

super.dispose();
}
Expand Down
22 changes: 10 additions & 12 deletions src/vs/base/parts/tree/browser/treeView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,6 @@ import _ = require('vs/base/parts/tree/browser/tree');
import { IViewItem } from 'vs/base/parts/tree/browser/treeViewModel';
import {KeyCode} from 'vs/base/common/keyCodes';

export interface IRow {
element: HTMLElement;
templateId: string;
templateData: any;
}

function getLastScrollTime(element: HTMLElement): number {
var value = element.getAttribute('last-scroll-time');
return value ? parseInt(value, 10) : 0;
Expand All @@ -45,15 +39,15 @@ function removeFromParent(element: HTMLElement): void {

export class RowCache implements Lifecycle.IDisposable {

private _cache: { [templateId:string]: IRow[]; };
private scrollingRow: IRow;
private _cache: { [templateId:string]: _.IRow[]; };
private scrollingRow: _.IRow;

constructor(private context: _.ITreeContext) {
this._cache = { '': [] };
this.scrollingRow = null;
}

public alloc(templateId: string): IRow {
public alloc(templateId: string): _.IRow {
var result = this.cache(templateId).pop();

if (!result) {
Expand All @@ -73,7 +67,7 @@ export class RowCache implements Lifecycle.IDisposable {
return result;
}

public release(templateId: string, row: IRow): void {
public release(templateId: string, row: _.IRow): void {
var lastScrollTime = getLastScrollTime(row.element);

if (!lastScrollTime) {
Expand Down Expand Up @@ -102,7 +96,7 @@ export class RowCache implements Lifecycle.IDisposable {
DOM.addClass(this.scrollingRow.element, 'scrolling');
}

private cache(templateId: string): IRow[] {
private cache(templateId: string): _.IRow[] {
return this._cache[templateId] || (this._cache[templateId] = []);
}

Expand Down Expand Up @@ -142,7 +136,7 @@ export class ViewItem implements IViewItem {

public model: Model.Item;
public id: string;
protected row: IRow;
protected row: _.IRow;

public top: number;
public height: number;
Expand Down Expand Up @@ -284,6 +278,9 @@ export class ViewItem implements IViewItem {

if (!skipUserRender) {
this.context.renderer.renderElement(this.context.tree, this.model.getElement(), this.templateId, this.row.templateData);
if (this.context.decorator) {
this.context.decorator.decorate(this.context.tree, this.model.getElement(), this.templateId, this.row);
}
}
}

Expand Down Expand Up @@ -451,6 +448,7 @@ export class TreeView extends HeightMap {
filter: context.filter,
sorter: context.sorter,
tree: context.tree,
decorator: context.decorator,
accessibilityProvider: context.accessibilityProvider,
options: context.options,
cache: new RowCache(context)
Expand Down
2 changes: 2 additions & 0 deletions src/vs/workbench/browser/workbench.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {Identifiers} from 'vs/workbench/common/constants';
import {isWindows, isLinux} from 'vs/base/common/platform';
import {IOptions} from 'vs/workbench/common/options';
import {IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions} from 'vs/workbench/common/contributions';
import {IDecoratorRegistry, Extensions as DecoratorExtensions} from 'vs/workbench/parts/decorators/decoratorRegistry';
import {IEditorRegistry, Extensions as EditorExtensions, BaseEditor} from 'vs/workbench/browser/parts/editor/baseEditor';
import {TextEditorOptions, EditorInput, EditorOptions} from 'vs/workbench/common/editor';
import {Part} from 'vs/workbench/browser/part';
Expand Down Expand Up @@ -397,6 +398,7 @@ export class Workbench implements IPartService {
<IActionBarRegistry>Registry.as(ActionBarExtensions.Actionbar).setInstantiationService(this.instantiationService);
<IWorkbenchContributionsRegistry>Registry.as(WorkbenchExtensions.Workbench).setInstantiationService(this.instantiationService);
<IEditorRegistry>Registry.as(EditorExtensions.Editors).setInstantiationService(this.instantiationService);
<IDecoratorRegistry>Registry.as(DecoratorExtensions.Decorators).setInstantiationService(this.instantiationService);
}

private initSettings(): void {
Expand Down
46 changes: 46 additions & 0 deletions src/vs/workbench/parts/decorators/decoratorRegistry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';

import {Registry, BaseRegistry} from 'vs/platform/platform';
import {IConstructorSignature0} from 'vs/platform/instantiation/common/instantiation';
import tree = require('vs/base/parts/tree/browser/tree');

export namespace Extensions {
export const Decorators = 'decorator.contributions.kind';
}

export type IDecoratorSignature = IConstructorSignature0<tree.IDecorator>;

export interface IDecoratorRegistry {

/**
* Registers a decorator to the platform that will be loaded when the workbench starts and disposed when
* the workbench shuts down.
*/
registerDecorator(decorator: IDecoratorSignature): void;

/**
* Returns all decorators that are known to the platform.
*/
getDecorators(): tree.IDecorator[];
}

class DecorationsRegistry extends BaseRegistry<tree.IDecorator> implements IDecoratorRegistry {

public registerDecorator(ctor: IDecoratorSignature): void {
super._register(ctor);
}

public getDecorators(): tree.IDecorator[] {
return super._getInstances();
}

public setDecorators(contributions: tree.IDecorator[]): void {
super._setInstances(contributions);
}
}

Registry.add(Extensions.Decorators, new DecorationsRegistry());
31 changes: 31 additions & 0 deletions src/vs/workbench/parts/decorators/treeDecorator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import tree = require('vs/base/parts/tree/browser/tree');
import lifecycle = require('vs/base/common/lifecycle');
import {Registry} from 'vs/platform/platform';
import {IDecoratorRegistry, Extensions as DecoratorExtensions} from 'vs/workbench/parts/decorators/decoratorRegistry';

export class TreeDecorator implements tree.IDecorator {

protected decorators: tree.IDecorator[] = [];
protected toDispose: lifecycle.IDisposable[] = [];
constructor() {
}

public onActivate(tree: tree.ITree): void {
this.decorators = Registry.as<IDecoratorRegistry>(DecoratorExtensions.Decorators).getDecorators();
this.decorators.forEach(decorator=>decorator.onActivate(tree));
}

public decorate(tree: tree.ITree, element: any, templateId: string, row: tree.IRow): void {
this.decorators.forEach(decorator=>decorator.decorate(tree,element,templateId, row));
}

public dispose(): void {
this.decorators.forEach(decorator => decorator.dispose());
this.toDispose.forEach(item => item.dispose());
}
}
3 changes: 3 additions & 0 deletions src/vs/workbench/parts/files/browser/views/explorerView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import paths = require('vs/base/common/paths');
import {Action, IActionRunner, IAction} from 'vs/base/common/actions';
import {prepareActions} from 'vs/workbench/browser/actionBarRegistry';
import {ITree} from 'vs/base/parts/tree/browser/tree';
import {TreeDecorator} from 'vs/workbench/parts/decorators/treeDecorator';
import {Tree} from 'vs/base/parts/tree/browser/treeImpl';
import {EditorOptions} from 'vs/workbench/common/editor';
import {LocalFileChangeEvent, IFilesConfiguration} from 'vs/workbench/parts/files/common/files';
Expand Down Expand Up @@ -330,6 +331,7 @@ export class ExplorerView extends CollapsibleViewletView {
let dataSource = this.instantiationService.createInstance(FileDataSource);
let renderer = this.instantiationService.createInstance(FileRenderer, this.viewletState, this.actionRunner);
let controller = this.instantiationService.createInstance(FileController, this.viewletState);
let decorator = this.instantiationService.createInstance(TreeDecorator);
let sorter = new FileSorter();
this.filter = this.instantiationService.createInstance(FileFilter);
let dnd = this.instantiationService.createInstance(FileDragAndDrop);
Expand All @@ -340,6 +342,7 @@ export class ExplorerView extends CollapsibleViewletView {
renderer: renderer,
controller: controller,
sorter: sorter,
decorator: decorator,
filter: this.filter,
dnd: dnd,
accessibilityProvider: accessibility
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ export class FileRenderer extends ActionsRenderer implements IRenderer {
constructor(
state: FileViewletState,
actionRunner: IActionRunner,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IContextViewService private contextViewService: IContextViewService
) {
super({
Expand Down
3 changes: 3 additions & 0 deletions src/vs/workbench/parts/files/browser/views/openEditorsView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {IAction, IActionRunner} from 'vs/base/common/actions';
import dom = require('vs/base/browser/dom');
import {CollapsibleState} from 'vs/base/browser/ui/splitview/splitview';
import {Tree} from 'vs/base/parts/tree/browser/treeImpl';
import {TreeDecorator} from 'vs/workbench/parts/decorators/treeDecorator';
import {IContextMenuService} from 'vs/platform/contextview/browser/contextView';
import {IMessageService} from 'vs/platform/message/common/message';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
Expand Down Expand Up @@ -93,13 +94,15 @@ export class OpenEditorsView extends AdaptiveCollapsibleViewletView {
const dataSource = this.instantiationService.createInstance(DataSource);
const actionProvider = this.instantiationService.createInstance(ActionProvider, this.model);
const renderer = this.instantiationService.createInstance(Renderer, actionProvider, this.model);
const decorator = this.instantiationService.createInstance(TreeDecorator);
const controller = this.instantiationService.createInstance(Controller, actionProvider, this.model);
const accessibilityProvider = this.instantiationService.createInstance(AccessibilityProvider);
const dnd = this.instantiationService.createInstance(DragAndDrop);

this.tree = new Tree(this.treeContainer, {
dataSource,
renderer,
decorator,
controller,
accessibilityProvider,
dnd
Expand Down
Loading

0 comments on commit b47ebd3

Please sign in to comment.