Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add WebviewPanel.iconPath #54912

Merged
merged 5 commits into from
Jul 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion extensions/markdown-language-features/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export function activate(context: vscode.ExtensionContext) {
const telemetryReporter = loadDefaultTelemetryReporter();
context.subscriptions.push(telemetryReporter);

const contributions = getMarkdownExtensionContributions();
const contributions = getMarkdownExtensionContributions(context);

const cspArbiter = new ExtensionContentSecurityPolicyArbiter(context.globalState, context.workspaceState);
const engine = new MarkdownEngine(contributions, githubSlugifier);
Expand Down
9 changes: 9 additions & 0 deletions extensions/markdown-language-features/src/features/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,14 @@ export class MarkdownPreview {
this.editor.title = MarkdownPreview.getPreviewTitle(this._resource, this._locked);
}

private get iconPath() {
const root = path.join(this._contributions.extensionPath, 'media');
return {
light: vscode.Uri.file(path.join(root, 'Preview.svg')),
dark: vscode.Uri.file(path.join(root, 'Preview_inverse.svg'))
};
}

private isPreviewOf(resource: vscode.Uri): boolean {
return this._resource.fsPath === resource.fsPath;
}
Expand Down Expand Up @@ -327,6 +335,7 @@ export class MarkdownPreview {
const content = await this._contentProvider.provideTextDocumentContent(document, this._previewConfigurations, this.line, this.state);
if (this._resource === resource) {
this.editor.title = MarkdownPreview.getPreviewTitle(this._resource, this._locked);
this.editor.iconPath = this.iconPath;
this.editor.webview.options = MarkdownPreview.getWebviewOptions(resource, this._contributions);
this.editor.webview.html = content;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const resolveExtensionResources = (extension: vscode.Extension<any>, resourcePat
};

export interface MarkdownContributions {
readonly extensionPath: string;
readonly previewScripts: vscode.Uri[];
readonly previewStyles: vscode.Uri[];
readonly markdownItPlugins: Thenable<(md: any) => any>[];
Expand All @@ -40,6 +41,10 @@ class MarkdownExtensionContributions implements MarkdownContributions {

private _loaded = false;

public constructor(
public readonly extensionPath: string,
) { }

public get previewScripts(): vscode.Uri[] {
this.ensureLoaded();
return this._scripts;
Expand Down Expand Up @@ -111,6 +116,6 @@ class MarkdownExtensionContributions implements MarkdownContributions {
}
}

export function getMarkdownExtensionContributions(): MarkdownContributions {
return new MarkdownExtensionContributions();
export function getMarkdownExtensionContributions(context: vscode.ExtensionContext): MarkdownContributions {
return new MarkdownExtensionContributions(context.extensionPath);
}
1 change: 1 addition & 0 deletions extensions/markdown-language-features/src/test/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { MarkdownContributions } from '../markdownExtensions';
import { githubSlugifier } from '../slugify';

const emptyContributions = new class implements MarkdownContributions {
readonly extensionPath = '';
readonly previewScripts: vscode.Uri[] = [];
readonly previewStyles: vscode.Uri[] = [];
readonly previewResourceRoots: vscode.Uri[] = [];
Expand Down
5 changes: 5 additions & 0 deletions src/vs/vscode.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5500,6 +5500,11 @@ declare module 'vscode' {
*/
title: string;

/**
* Icon for the panel shown in UI.
*/
iconPath?: Uri | { light: Uri; dark: Uri };

/**
* Webview belonging to the panel.
*/
Expand Down
71 changes: 65 additions & 6 deletions src/vs/workbench/api/electron-browser/mainThreadWebview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,24 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import * as dom from 'vs/base/browser/dom';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import * as map from 'vs/base/common/map';
import URI, { UriComponents } from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import { localize } from 'vs/nls';
import { EditorViewColumn, viewColumnToEditorGroup, editorGroupToViewColumn } from 'vs/workbench/api/shared/editor';
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { ExtHostContext, ExtHostWebviewsShape, IExtHostContext, MainContext, MainThreadWebviewsShape, WebviewPanelHandle } from 'vs/workbench/api/node/extHost.protocol';
import { editorGroupToViewColumn, EditorViewColumn, viewColumnToEditorGroup } from 'vs/workbench/api/shared/editor';
import { WebviewEditor } from 'vs/workbench/parts/webview/electron-browser/webviewEditor';
import { WebviewEditorInput } from 'vs/workbench/parts/webview/electron-browser/webviewEditorInput';
import { IWebviewEditorService, WebviewInputOptions, WebviewReviver, ICreateWebViewShowOptions } from 'vs/workbench/parts/webview/electron-browser/webviewEditorService';
import { ICreateWebViewShowOptions, IWebviewEditorService, WebviewInputOptions, WebviewReviver } from 'vs/workbench/parts/webview/electron-browser/webviewEditorService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
import { extHostNamedCustomer } from './extHostCustomers';
import * as vscode from 'vscode';
import { extHostNamedCustomer } from './extHostCustomers';

@extHostNamedCustomer(MainContext.MainThreadWebviews)
export class MainThreadWebviews implements MainThreadWebviewsShape, WebviewReviver {
Expand All @@ -29,6 +30,39 @@ export class MainThreadWebviews implements MainThreadWebviewsShape, WebviewReviv

private static revivalPool = 0;

private static _styleElement?: HTMLStyleElement;

private static _icons = new Map<number, { light: URI, dark: URI }>();

private static updateStyleElement(
webview: WebviewEditorInput,
iconPath: { light: URI, dark: URI } | undefined
) {
const id = webview.getId();
if (!this._styleElement) {
this._styleElement = dom.createStyleSheet();
this._styleElement.className = 'webview-icons';
}

if (!iconPath) {
this._icons.delete(id);
} else {
this._icons.set(id, iconPath);
}

const cssRules: string[] = [];
this._icons.forEach((value, key) => {
const webviewSelector = `.show-file-icons .webview-${key}-name-file-icon::before`;
if (URI.isUri(value)) {
cssRules.push(`${webviewSelector} { content: ""; background-image: url(${value.toString()}); }`);
} else {
cssRules.push(`${webviewSelector} { content: ""; background-image: url(${value.light.toString()}); }`);
cssRules.push(`.vs-dark ${webviewSelector} { content: ""; background-image: url(${value.dark.toString()}); }`);
}
});
this._styleElement.innerHTML = cssRules.join('\n');
}

private _toDispose: IDisposable[] = [];

private readonly _proxy: ExtHostWebviewsShape;
Expand Down Expand Up @@ -96,6 +130,11 @@ export class MainThreadWebviews implements MainThreadWebviewsShape, WebviewReviv
webview.setName(value);
}

public $setIconPath(handle: WebviewPanelHandle, value: { light: UriComponents, dark: UriComponents } | undefined): void {
const webview = this.getWebview(handle);
MainThreadWebviews.updateStyleElement(webview, reviveWebviewIcon(value));
}

public $setHtml(handle: WebviewPanelHandle, value: string): void {
const webview = this.getWebview(handle);
webview.html = value;
Expand Down Expand Up @@ -185,9 +224,16 @@ export class MainThreadWebviews implements MainThreadWebviewsShape, WebviewReviv
onDidClickLink: uri => this.onDidClickLink(handle, uri),
onMessage: message => this._proxy.$onMessage(handle, message),
onDispose: () => {
const cleanUp = () => {
const webview = this._webviews.get(handle);
if (webview) {
MainThreadWebviews.updateStyleElement(webview, undefined);
}
this._webviews.delete(handle);
};
this._proxy.$onDidDisposeWebviewPanel(handle).then(
() => this._webviews.delete(handle),
() => this._webviews.delete(handle));
cleanUp,
cleanUp);
}
};
}
Expand Down Expand Up @@ -297,3 +343,16 @@ function reviveWebviewOptions(options: WebviewInputOptions): WebviewInputOptions
localResourceRoots: Array.isArray(options.localResourceRoots) ? options.localResourceRoots.map(URI.revive) : undefined
};
}

function reviveWebviewIcon(
value: { light: UriComponents, dark: UriComponents } | undefined
): { light: URI, dark: URI } | undefined {
if (!value) {
return undefined;
}

return {
light: URI.revive(value.light),
dark: URI.revive(value.dark)
};
}
1 change: 1 addition & 0 deletions src/vs/workbench/api/node/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,7 @@ export interface MainThreadWebviewsShape extends IDisposable {
$disposeWebview(handle: WebviewPanelHandle): void;
$reveal(handle: WebviewPanelHandle, viewColumn: EditorViewColumn | null, preserveFocus: boolean): void;
$setTitle(handle: WebviewPanelHandle, value: string): void;
$setIconPath(handle: WebviewPanelHandle, value: { light: UriComponents, dark: UriComponents } | undefined): void;
$setHtml(handle: WebviewPanelHandle, value: string): void;
$setOptions(handle: WebviewPanelHandle, options: vscode.WebviewOptions): void;
$postMessage(handle: WebviewPanelHandle, value: any): Thenable<boolean>;
Expand Down
28 changes: 23 additions & 5 deletions src/vs/workbench/api/node/extHostWebview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { MainContext, MainThreadWebviewsShape, IMainContext, ExtHostWebviewsShape, WebviewPanelHandle, WebviewPanelViewState } from './extHost.protocol';
import * as vscode from 'vscode';
import { Event, Emitter } from 'vs/base/common/event';
import { Emitter, Event } from 'vs/base/common/event';
import URI from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import * as typeConverters from 'vs/workbench/api/node/extHostTypeConverters';
import { EditorViewColumn } from 'vs/workbench/api/shared/editor';
import { TPromise } from 'vs/base/common/winjs.base';
import * as vscode from 'vscode';
import { ExtHostWebviewsShape, IMainContext, MainContext, MainThreadWebviewsShape, WebviewPanelHandle, WebviewPanelViewState } from './extHost.protocol';
import { Disposable } from './extHostTypes';
import URI from 'vs/base/common/uri';


type IconPath = URI | { light: URI, dark: URI };

export class ExtHostWebview implements vscode.Webview {
private readonly _handle: WebviewPanelHandle;
Expand Down Expand Up @@ -78,6 +81,7 @@ export class ExtHostWebviewPanel implements vscode.WebviewPanel {
private readonly _proxy: MainThreadWebviewsShape;
private readonly _viewType: string;
private _title: string;
private _iconPath: IconPath;

private readonly _options: vscode.WebviewPanelOptions;
private readonly _webview: ExtHostWebview;
Expand Down Expand Up @@ -150,6 +154,20 @@ export class ExtHostWebviewPanel implements vscode.WebviewPanel {
}
}

get iconPath(): IconPath | undefined {
this.assertNotDisposed();
return this._iconPath;
}

set iconPath(value: IconPath | undefined) {
this.assertNotDisposed();
if (this._iconPath !== value) {
this._iconPath = value;

this._proxy.$setIconPath(this._handle, URI.isUri(value) ? { light: value, dark: value } : value);
}
}

get options() {
return this._options;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import * as DOM from 'vs/base/browser/dom';
import { domEvent } from 'vs/base/browser/event';
import { CancellationToken } from 'vs/base/common/cancellation';
import { Emitter, Event } from 'vs/base/common/event';
import { IDisposable } from 'vs/base/common/lifecycle';
import URI from 'vs/base/common/uri';
Expand All @@ -14,13 +15,12 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { EditorOptions } from 'vs/workbench/common/editor';
import { IEditorGroup } from 'vs/workbench/services/group/common/editorGroupsService';
import { WebviewEditorInput } from 'vs/workbench/parts/webview/electron-browser/webviewEditorInput';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IEditorGroup } from 'vs/workbench/services/group/common/editorGroupsService';
import { IPartService, Parts } from 'vs/workbench/services/part/common/partService';
import { BaseWebviewEditor, KEYBINDING_CONTEXT_WEBVIEWEDITOR_FIND_WIDGET_INPUT_FOCUSED, KEYBINDING_CONTEXT_WEBVIEWEDITOR_FOCUS, KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_VISIBLE } from './baseWebviewEditor';
import { WebviewElement } from './webviewElement';
import { CancellationToken } from 'vs/base/common/cancellation';

export class WebviewEditor extends BaseWebviewEditor {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { Emitter } from 'vs/base/common/event';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import URI from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import { IEditorModel } from 'vs/platform/editor/common/editor';
import { EditorInput, EditorModel, IEditorInput, GroupIdentifier } from 'vs/workbench/common/editor';
import { EditorInput, EditorModel, GroupIdentifier, IEditorInput } from 'vs/workbench/common/editor';
import { IPartService, Parts } from 'vs/workbench/services/part/common/partService';
import * as vscode from 'vscode';
import { WebviewEvents, WebviewInputOptions, WebviewReviver } from './webviewEditorService';
import { WebviewElement } from './webviewElement';
import * as vscode from 'vscode';

export class WebviewEditorInput extends EditorInput {
private static handlePool = 0;
Expand All @@ -35,6 +36,7 @@ export class WebviewEditorInput extends EditorInput {
private _revived: boolean = false;

public readonly extensionLocation: URI | undefined;
private readonly _id: number;

constructor(
public readonly viewType: string,
Expand All @@ -47,6 +49,7 @@ export class WebviewEditorInput extends EditorInput {
@IPartService private readonly _partService: IPartService,
) {
super();
this._id = WebviewEditorInput.handlePool++;
this._name = name;
this._options = options;
this._events = events;
Expand All @@ -58,6 +61,13 @@ export class WebviewEditorInput extends EditorInput {
return WebviewEditorInput.typeId;
}

public getId(): number {
return this._id;
}

private readonly _onDidChangeIcon = this._register(new Emitter<void>());
public readonly onDidChangeIcon = this._onDidChangeIcon.event;

public dispose() {
this.disposeWebview();

Expand All @@ -76,7 +86,10 @@ export class WebviewEditorInput extends EditorInput {
}

public getResource(): URI {
return null;
return URI.from({
scheme: 'webview-panel',
path: `webview-panel/webview-${this._id}`
});
}

public getName(): string {
Expand Down Expand Up @@ -169,9 +182,8 @@ export class WebviewEditorInput extends EditorInput {

public get container(): HTMLElement {
if (!this._container) {
const id = WebviewEditorInput.handlePool++;
this._container = document.createElement('div');
this._container.id = `webview-${id}`;
this._container.id = `webview-${this._id}`;
this._partService.getContainer(Parts.EDITOR_PART).appendChild(this._container);
}
return this._container;
Expand Down