mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-03-30 08:40:29 -04:00
Vscode merge (#4582)
* Merge from vscode 37cb23d3dd4f9433d56d4ba5ea3203580719a0bd * fix issues with merges * bump node version in azpipe * replace license headers * remove duplicate launch task * fix build errors * fix build errors * fix tslint issues * working through package and linux build issues * more work * wip * fix packaged builds * working through linux build errors * wip * wip * wip * fix mac and linux file limits * iterate linux pipeline * disable editor typing * revert series to parallel * remove optimize vscode from linux * fix linting issues * revert testing change * add work round for new node * readd packaging for extensions * fix issue with angular not resolving decorator dependencies
This commit is contained in:
256
src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts
Normal file
256
src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts
Normal file
@@ -0,0 +1,256 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { IDataSource, ITree, IRenderer } from 'vs/base/parts/tree/browser/tree';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { IExtensionsWorkbenchService, IExtension } from 'vs/workbench/contrib/extensions/common/extensions';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { WorkbenchTreeController, WorkbenchTree, IListService } from 'vs/platform/list/browser/listService';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
|
||||
export interface IExtensionTemplateData {
|
||||
icon: HTMLImageElement;
|
||||
name: HTMLElement;
|
||||
identifier: HTMLElement;
|
||||
author: HTMLElement;
|
||||
extensionDisposables: IDisposable[];
|
||||
extensionData: IExtensionData;
|
||||
}
|
||||
|
||||
export interface IUnknownExtensionTemplateData {
|
||||
identifier: HTMLElement;
|
||||
}
|
||||
|
||||
export interface IExtensionData {
|
||||
extension: IExtension;
|
||||
hasChildren: boolean;
|
||||
getChildren: () => Promise<IExtensionData[] | null>;
|
||||
parent: IExtensionData | null;
|
||||
}
|
||||
|
||||
export class DataSource implements IDataSource {
|
||||
|
||||
public getId(tree: ITree, { extension, parent }: IExtensionData): string {
|
||||
return parent ? this.getId(tree, parent) + '/' + extension.identifier.id : extension.identifier.id;
|
||||
}
|
||||
|
||||
public hasChildren(tree: ITree, { hasChildren }: IExtensionData): boolean {
|
||||
return hasChildren;
|
||||
}
|
||||
|
||||
public getChildren(tree: ITree, extensionData: IExtensionData): Promise<any> {
|
||||
return extensionData.getChildren();
|
||||
}
|
||||
|
||||
public getParent(tree: ITree, { parent }: IExtensionData): Promise<any> {
|
||||
return Promise.resolve(parent);
|
||||
}
|
||||
}
|
||||
|
||||
export class Renderer implements IRenderer {
|
||||
|
||||
private static readonly EXTENSION_TEMPLATE_ID = 'extension-template';
|
||||
private static readonly UNKNOWN_EXTENSION_TEMPLATE_ID = 'unknown-extension-template';
|
||||
|
||||
constructor(@IInstantiationService private readonly instantiationService: IInstantiationService) {
|
||||
}
|
||||
|
||||
public getHeight(tree: ITree, element: IExtensionData): number {
|
||||
return 62;
|
||||
}
|
||||
|
||||
public getTemplateId(tree: ITree, { extension }: IExtensionData): string {
|
||||
return extension ? Renderer.EXTENSION_TEMPLATE_ID : Renderer.UNKNOWN_EXTENSION_TEMPLATE_ID;
|
||||
}
|
||||
|
||||
public renderTemplate(tree: ITree, templateId: string, container: HTMLElement): any {
|
||||
if (Renderer.EXTENSION_TEMPLATE_ID === templateId) {
|
||||
return this.renderExtensionTemplate(tree, container);
|
||||
}
|
||||
return this.renderUnknownExtensionTemplate(tree, container);
|
||||
}
|
||||
|
||||
private renderExtensionTemplate(tree: ITree, container: HTMLElement): IExtensionTemplateData {
|
||||
dom.addClass(container, 'extension');
|
||||
|
||||
const icon = dom.append(container, dom.$<HTMLImageElement>('img.icon'));
|
||||
const details = dom.append(container, dom.$('.details'));
|
||||
|
||||
const header = dom.append(details, dom.$('.header'));
|
||||
const name = dom.append(header, dom.$('span.name'));
|
||||
const openExtensionAction = this.instantiationService.createInstance(OpenExtensionAction);
|
||||
const extensionDisposables = [dom.addDisposableListener(name, 'click', (e: MouseEvent) => {
|
||||
tree.setFocus(openExtensionAction.extensionData);
|
||||
tree.setSelection([openExtensionAction.extensionData]);
|
||||
openExtensionAction.run(e.ctrlKey || e.metaKey);
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
})];
|
||||
const identifier = dom.append(header, dom.$('span.identifier'));
|
||||
|
||||
const footer = dom.append(details, dom.$('.footer'));
|
||||
const author = dom.append(footer, dom.$('.author'));
|
||||
return {
|
||||
icon,
|
||||
name,
|
||||
identifier,
|
||||
author,
|
||||
extensionDisposables,
|
||||
set extensionData(extensionData: IExtensionData) {
|
||||
openExtensionAction.extensionData = extensionData;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private renderUnknownExtensionTemplate(tree: ITree, container: HTMLElement): IUnknownExtensionTemplateData {
|
||||
const messageContainer = dom.append(container, dom.$('div.unknown-extension'));
|
||||
dom.append(messageContainer, dom.$('span.error-marker')).textContent = localize('error', "Error");
|
||||
dom.append(messageContainer, dom.$('span.message')).textContent = localize('Unknown Extension', "Unknown Extension:");
|
||||
|
||||
const identifier = dom.append(messageContainer, dom.$('span.message'));
|
||||
return { identifier };
|
||||
}
|
||||
|
||||
public renderElement(tree: ITree, element: IExtensionData, templateId: string, templateData: any): void {
|
||||
if (templateId === Renderer.EXTENSION_TEMPLATE_ID) {
|
||||
this.renderExtension(tree, element, templateData);
|
||||
return;
|
||||
}
|
||||
this.renderUnknownExtension(tree, element, templateData);
|
||||
}
|
||||
|
||||
private renderExtension(tree: ITree, extensionData: IExtensionData, data: IExtensionTemplateData): void {
|
||||
const extension = extensionData.extension;
|
||||
const onError = Event.once(domEvent(data.icon, 'error'));
|
||||
onError(() => data.icon.src = extension.iconUrlFallback, null, data.extensionDisposables);
|
||||
data.icon.src = extension.iconUrl;
|
||||
|
||||
if (!data.icon.complete) {
|
||||
data.icon.style.visibility = 'hidden';
|
||||
data.icon.onload = () => data.icon.style.visibility = 'inherit';
|
||||
} else {
|
||||
data.icon.style.visibility = 'inherit';
|
||||
}
|
||||
|
||||
data.name.textContent = extension.displayName;
|
||||
data.identifier.textContent = extension.identifier.id;
|
||||
data.author.textContent = extension.publisherDisplayName;
|
||||
data.extensionData = extensionData;
|
||||
}
|
||||
|
||||
private renderUnknownExtension(tree: ITree, { extension }: IExtensionData, data: IUnknownExtensionTemplateData): void {
|
||||
data.identifier.textContent = extension.identifier.id;
|
||||
}
|
||||
|
||||
public disposeTemplate(tree: ITree, templateId: string, templateData: any): void {
|
||||
if (templateId === Renderer.EXTENSION_TEMPLATE_ID) {
|
||||
templateData.extensionDisposables = dispose((<IExtensionTemplateData>templateData).extensionDisposables);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class Controller extends WorkbenchTreeController {
|
||||
|
||||
constructor(
|
||||
@IExtensionsWorkbenchService private readonly extensionsWorkdbenchService: IExtensionsWorkbenchService,
|
||||
@IConfigurationService configurationService: IConfigurationService
|
||||
) {
|
||||
super({}, configurationService);
|
||||
|
||||
// TODO@Sandeep this should be a command
|
||||
this.downKeyBindingDispatcher.set(KeyMod.CtrlCmd | KeyCode.Enter, (tree: ITree, event: any) => this.openExtension(tree, true));
|
||||
}
|
||||
|
||||
protected onLeftClick(tree: ITree, element: IExtensionData, event: IMouseEvent): boolean {
|
||||
let currentFocused = tree.getFocus();
|
||||
if (super.onLeftClick(tree, element, event)) {
|
||||
if (element.parent === null) {
|
||||
if (currentFocused) {
|
||||
tree.setFocus(currentFocused);
|
||||
} else {
|
||||
tree.focusFirst();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public openExtension(tree: ITree, sideByside: boolean): boolean {
|
||||
const element: IExtensionData = tree.getFocus();
|
||||
if (element.extension) {
|
||||
this.extensionsWorkdbenchService.open(element.extension, sideByside);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class OpenExtensionAction extends Action {
|
||||
|
||||
private _extensionData: IExtensionData;
|
||||
|
||||
constructor(@IExtensionsWorkbenchService private readonly extensionsWorkdbenchService: IExtensionsWorkbenchService) {
|
||||
super('extensions.action.openExtension', '');
|
||||
}
|
||||
|
||||
public set extensionData(extension: IExtensionData) {
|
||||
this._extensionData = extension;
|
||||
}
|
||||
|
||||
public get extensionData(): IExtensionData {
|
||||
return this._extensionData;
|
||||
}
|
||||
|
||||
run(sideByside: boolean): Promise<any> {
|
||||
return this.extensionsWorkdbenchService.open(this.extensionData.extension, sideByside);
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtensionsTree extends WorkbenchTree {
|
||||
|
||||
constructor(
|
||||
input: IExtensionData,
|
||||
container: HTMLElement,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IListService listService: IListService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IConfigurationService configurationService: IConfigurationService
|
||||
) {
|
||||
const renderer = instantiationService.createInstance(Renderer);
|
||||
const controller = instantiationService.createInstance(Controller);
|
||||
|
||||
super(
|
||||
container,
|
||||
{
|
||||
dataSource: new DataSource(),
|
||||
renderer,
|
||||
controller
|
||||
}, {
|
||||
indentPixels: 40,
|
||||
twistiePixels: 20
|
||||
},
|
||||
contextKeyService, listService, themeService, instantiationService, configurationService
|
||||
);
|
||||
|
||||
this.setInput(input);
|
||||
|
||||
this.disposables.push(this.onDidChangeSelection(event => {
|
||||
if (event && event.payload && event.payload.origin === 'keyboard') {
|
||||
controller.openExtension(this, false);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user