Merge from vscode 9bc92b48d945144abb405b9e8df05e18accb9148

This commit is contained in:
ADS Merger
2020-02-19 03:11:35 +00:00
parent 98584d32a7
commit 1e308639e5
253 changed files with 6414 additions and 2296 deletions

View File

@@ -240,7 +240,7 @@ export class ResourcesDropHandler {
// Untitled: always ensure that we open a new untitled editor for each file we drop
if (droppedDirtyEditor.resource.scheme === Schemas.untitled) {
const untitledEditorResource = this.editorService.createInput({ mode: droppedDirtyEditor.mode, encoding: droppedDirtyEditor.encoding, forceUntitled: true }).getResource();
const untitledEditorResource = this.editorService.createInput({ mode: droppedDirtyEditor.mode, encoding: droppedDirtyEditor.encoding, forceUntitled: true }).resource;
if (untitledEditorResource) {
droppedDirtyEditor.resource = untitledEditorResource;
}
@@ -299,7 +299,7 @@ export class ResourcesDropHandler {
// Open in separate windows if we drop workspaces or just one folder
if (toOpen.length > folderURIs.length || folderURIs.length === 1) {
await this.hostService.openWindow(toOpen, { forceReuseWindow: true });
await this.hostService.openWindow(toOpen);
}
// folders.length > 1: Multiple folders: Create new workspace with folders and open

View File

@@ -239,7 +239,7 @@ enum Redraw {
class ResourceLabelWidget extends IconLabel {
private _onDidRender = this._register(new Emitter<void>());
readonly onDidRender: Event<void> = this._onDidRender.event;
readonly onDidRender = this._onDidRender.event;
private readonly renderDisposables = this._register(new DisposableStore());

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { Event, Emitter } from 'vs/base/common/event';
import { Emitter } from 'vs/base/common/event';
import { EventType, addDisposableListener, addClass, removeClass, isAncestor, getClientArea, Dimension, toggleClass, position, size } from 'vs/base/browser/dom';
import { onDidChangeFullscreen, isFullscreen } from 'vs/base/browser/browser';
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
@@ -25,6 +25,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation
import { LifecyclePhase, StartupKind, ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { MenuBarVisibility, getTitleBarStyle, getMenuBarVisibility } from 'vs/platform/windows/common/windows';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IEditor } from 'vs/editor/common/editorCommon';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IEditorService, IResourceEditor } from 'vs/workbench/services/editor/common/editorService';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
@@ -40,6 +41,7 @@ import { assertIsDefined } from 'vs/base/common/types';
import { INotificationService, NotificationsFilter } from 'vs/platform/notification/common/notification';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { WINDOW_ACTIVE_BORDER, WINDOW_INACTIVE_BORDER } from 'vs/workbench/common/theme';
import { LineNumbersType } from 'vs/editor/common/config/editorOptions';
enum Settings {
ACTIVITYBAR_VISIBLE = 'workbench.activityBar.visible',
@@ -87,26 +89,26 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
//#region Events
private readonly _onZenModeChange: Emitter<boolean> = this._register(new Emitter<boolean>());
readonly onZenModeChange: Event<boolean> = this._onZenModeChange.event;
private readonly _onZenModeChange = this._register(new Emitter<boolean>());
readonly onZenModeChange = this._onZenModeChange.event;
private readonly _onFullscreenChange: Emitter<boolean> = this._register(new Emitter<boolean>());
readonly onFullscreenChange: Event<boolean> = this._onFullscreenChange.event;
private readonly _onFullscreenChange = this._register(new Emitter<boolean>());
readonly onFullscreenChange = this._onFullscreenChange.event;
private readonly _onCenteredLayoutChange: Emitter<boolean> = this._register(new Emitter<boolean>());
readonly onCenteredLayoutChange: Event<boolean> = this._onCenteredLayoutChange.event;
private readonly _onCenteredLayoutChange = this._register(new Emitter<boolean>());
readonly onCenteredLayoutChange = this._onCenteredLayoutChange.event;
private readonly _onMaximizeChange: Emitter<boolean> = this._register(new Emitter<boolean>());
readonly onMaximizeChange: Event<boolean> = this._onMaximizeChange.event;
private readonly _onMaximizeChange = this._register(new Emitter<boolean>());
readonly onMaximizeChange = this._onMaximizeChange.event;
private readonly _onPanelPositionChange: Emitter<string> = this._register(new Emitter<string>());
readonly onPanelPositionChange: Event<string> = this._onPanelPositionChange.event;
private readonly _onPanelPositionChange = this._register(new Emitter<string>());
readonly onPanelPositionChange = this._onPanelPositionChange.event;
private readonly _onPartVisibilityChange: Emitter<void> = this._register(new Emitter<void>());
readonly onPartVisibilityChange: Event<void> = this._onPartVisibilityChange.event;
private readonly _onPartVisibilityChange = this._register(new Emitter<void>());
readonly onPartVisibilityChange = this._onPartVisibilityChange.event;
private readonly _onLayout = this._register(new Emitter<IDimension>());
readonly onLayout: Event<IDimension> = this._onLayout.event;
readonly onLayout = this._onLayout.event;
//#endregion
@@ -120,6 +122,8 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
private workbenchGrid!: SerializableGrid<ISerializableView>;
private editorWidgetSet = new Set<IEditor>();
private disposed: boolean | undefined;
private titleBarPartView!: ISerializableView;
@@ -690,18 +694,33 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
this.state.zenMode.active = !this.state.zenMode.active;
this.state.zenMode.transitionDisposables.clear();
const setLineNumbers = (lineNumbers?: any) => this.editorService.visibleTextEditorWidgets.forEach(editor => {
// To properly reset line numbers we need to read the configuration for each editor respecting it's uri.
if (!lineNumbers && isCodeEditor(editor) && editor.hasModel()) {
const model = editor.getModel();
lineNumbers = this.configurationService.getValue('editor.lineNumbers', { resource: model.uri, overrideIdentifier: model.getModeId() });
}
if (!lineNumbers) {
lineNumbers = this.configurationService.getValue('editor.lineNumbers');
}
const setLineNumbers = (lineNumbers?: LineNumbersType) => {
const setEditorLineNumbers = (editor: IEditor) => {
// To properly reset line numbers we need to read the configuration for each editor respecting it's uri.
if (!lineNumbers && isCodeEditor(editor) && editor.hasModel()) {
const model = editor.getModel();
lineNumbers = this.configurationService.getValue('editor.lineNumbers', { resource: model.uri, overrideIdentifier: model.getModeId() });
}
if (!lineNumbers) {
lineNumbers = this.configurationService.getValue('editor.lineNumbers');
}
editor.updateOptions({ lineNumbers });
});
editor.updateOptions({ lineNumbers });
};
if (!lineNumbers) {
// Reset line numbers on all editors visible and non-visible
for (const editor of this.editorWidgetSet) {
setEditorLineNumbers(editor);
}
this.editorWidgetSet.clear();
} else {
this.editorService.visibleTextEditorWidgets.forEach(editor => {
this.editorWidgetSet.add(editor);
setEditorLineNumbers(editor);
});
}
};
// Check if zen mode transitioned to full screen and if now we are out of zen mode
// -> we need to go out of full screen (same goes for the centered editor layout)

View File

@@ -34,7 +34,7 @@ export abstract class Part extends Component implements ISerializableView {
get dimension(): Dimension | undefined { return this._dimension; }
protected _onDidVisibilityChange = this._register(new Emitter<boolean>());
readonly onDidVisibilityChange: Event<boolean> = this._onDidVisibilityChange.event;
readonly onDidVisibilityChange = this._onDidVisibilityChange.event;
private parent: HTMLElement | undefined;
private titleArea: HTMLElement | undefined;

View File

@@ -19,7 +19,7 @@ import { Widget } from 'vs/base/browser/ui/widget';
import { isUndefinedOrNull } from 'vs/base/common/types';
import { LocalSelectionTransfer } from 'vs/workbench/browser/dnd';
import { ITheme } from 'vs/platform/theme/common/themeService';
import { Emitter, Event } from 'vs/base/common/event';
import { Emitter } from 'vs/base/common/event';
export interface ICompositeBarItem {
id: string;
@@ -61,7 +61,7 @@ export class CompositeBar extends Widget implements ICompositeBar {
private compositeTransfer: LocalSelectionTransfer<DraggedCompositeIdentifier>;
private readonly _onDidChange: Emitter<void> = this._register(new Emitter<void>());
readonly onDidChange: Event<void> = this._onDidChange.event;
readonly onDidChange = this._onDidChange.event;
constructor(
items: ICompositeBarItem[],

View File

@@ -39,7 +39,7 @@ export abstract class BaseEditor extends Panel implements IEditor {
readonly minimumHeight = DEFAULT_EDITOR_MIN_DIMENSIONS.height;
readonly maximumHeight = DEFAULT_EDITOR_MAX_DIMENSIONS.height;
readonly onDidSizeConstraintsChange: Event<{ width: number; height: number; } | undefined> = Event.None;
readonly onDidSizeConstraintsChange = Event.None;
protected _input: EditorInput | undefined;
protected _options: EditorOptions | undefined;
@@ -251,7 +251,7 @@ export class EditorMemento<T> implements IEditorMemento<T> {
private doGetResource(resourceOrEditor: URI | EditorInput): URI | undefined {
if (resourceOrEditor instanceof EditorInput) {
return resourceOrEditor.getResource();
return resourceOrEditor.resource;
}
return resourceOrEditor;

View File

@@ -231,7 +231,7 @@ export class BreadcrumbsControl {
input = input.master;
}
if (!input || !input.getResource() || !this._fileService.canHandleResource(input.getResource()!)) {
if (!input || !input.resource || !this._fileService.canHandleResource(input.resource!)) {
// cleanup and return when there is no input or when
// we cannot handle this input
this._ckBreadcrumbsPossible.set(false);
@@ -247,7 +247,7 @@ export class BreadcrumbsControl {
this._ckBreadcrumbsVisible.set(true);
this._ckBreadcrumbsPossible.set(true);
const uri = input.getResource()!;
const uri = input.resource;
const editor = this._getActiveCodeEditor();
const model = new EditorBreadcrumbsModel(
uri, editor,

View File

@@ -130,7 +130,7 @@ class UntitledTextEditorInputFactory implements IEditorInputFactory {
const untitledTextEditorInput = <UntitledTextEditorInput>editorInput;
let resource = untitledTextEditorInput.getResource();
let resource = untitledTextEditorInput.resource;
if (untitledTextEditorInput.model.hasAssociatedFilePath) {
resource = toLocalResource(resource, this.environmentService.configuration.remoteAuthority); // untitled with associated file path use the local schema
}

View File

@@ -542,7 +542,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
private toEditorTelemetryDescriptor(editor: EditorInput): object {
const descriptor = editor.getTelemetryDescriptor();
const resource = editor.getResource();
const resource = editor.resource;
const path = resource ? resource.scheme === Schemas.file ? resource.fsPath : resource.path : undefined;
if (resource && path) {
descriptor['resource'] = { mimeType: guessMimeTypes(resource).join(', '), scheme: resource.scheme, ext: extname(resource), path: hash(path) };
@@ -1580,7 +1580,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
get maximumHeight(): number { return this.editorControl.maximumHeight; }
private _onDidChange = this._register(new Relay<{ width: number; height: number; } | undefined>());
readonly onDidChange: Event<{ width: number; height: number; } | undefined> = this._onDidChange.event;
readonly onDidChange = this._onDidChange.event;
layout(width: number, height: number): void {
this.dimension = new Dimension(width, height);

View File

@@ -60,7 +60,7 @@ export class RangeHighlightDecorations extends Disposable {
private getEditor(resourceRange: IRangeHighlightDecoration): ICodeEditor | undefined {
const activeEditor = this.editorService.activeEditor;
const resource = activeEditor && activeEditor.getResource();
const resource = activeEditor && activeEditor.resource;
if (resource) {
if (resource.toString() === resourceRange.resource.toString()) {
return this.editorService.activeTextEditorWidget as ICodeEditor;

View File

@@ -331,8 +331,8 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor {
let modified: URI | undefined;
if (modelOrInput instanceof DiffEditorInput) {
original = modelOrInput.originalInput.getResource();
modified = modelOrInput.modifiedInput.getResource();
original = modelOrInput.originalInput.resource;
modified = modelOrInput.modifiedInput.resource;
} else {
original = modelOrInput.original.uri;
modified = modelOrInput.modified.uri;

View File

@@ -58,7 +58,7 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor {
this.editorMemento = this.getEditorMemento<IEditorViewState>(editorGroupService, BaseTextEditor.TEXT_EDITOR_VIEW_STATE_PREFERENCE_KEY, 100);
this._register(this.textResourceConfigurationService.onDidChangeConfiguration(e => {
const resource = this.getResource();
const resource = this.getActiveResource();
const value = resource ? this.textResourceConfigurationService.getValue<IEditorConfiguration>(resource) : undefined;
return this.handleConfigurationChangeEvent(value);
@@ -130,7 +130,7 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor {
// Editor for Text
this.editorContainer = parent;
this.editorControl = this._register(this.createEditorControl(parent, this.computeConfiguration(this.textResourceConfigurationService.getValue<IEditorConfiguration>(this.getResource()))));
this.editorControl = this._register(this.createEditorControl(parent, this.computeConfiguration(this.textResourceConfigurationService.getValue<IEditorConfiguration>(this.getActiveResource()))));
// Model & Language changes
const codeEditor = getCodeEditor(this.editorControl);
@@ -217,7 +217,7 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor {
}
getViewState(): IEditorViewState | undefined {
const resource = this.input?.getResource();
const resource = this.input?.resource;
if (resource) {
return withNullAsUndefined(this.retrieveTextEditorViewState(resource));
}
@@ -266,7 +266,7 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor {
private updateEditorConfiguration(configuration?: IEditorConfiguration): void {
if (!configuration) {
const resource = this.getResource();
const resource = this.getActiveResource();
if (resource) {
configuration = this.textResourceConfigurationService.getValue<IEditorConfiguration>(resource);
}
@@ -292,7 +292,7 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor {
}
}
private getResource(): URI | undefined {
private getActiveResource(): URI | undefined {
const codeEditor = getCodeEditor(this.editorControl);
if (codeEditor) {
const model = codeEditor.getModel();
@@ -302,7 +302,7 @@ export abstract class BaseTextEditor extends BaseEditor implements ITextEditor {
}
if (this.input) {
return this.input.getResource();
return this.input.resource;
}
return undefined;

View File

@@ -101,7 +101,7 @@ export class AbstractTextResourceEditor extends BaseTextEditor {
private restoreTextResourceEditorViewState(editor: EditorInput, control: IEditor) {
if (editor instanceof UntitledTextEditorInput || editor instanceof ResourceEditorInput) {
const viewState = this.loadTextEditorViewState(editor.getResource());
const viewState = this.loadTextEditorViewState(editor.resource);
if (viewState) {
control.restoreViewState(viewState);
}
@@ -111,7 +111,7 @@ export class AbstractTextResourceEditor extends BaseTextEditor {
protected getAriaLabel(): string {
let ariaLabel: string;
const inputName = this.input instanceof UntitledTextEditorInput ? basenameOrAuthority(this.input.getResource()) : this.input?.getName();
const inputName = this.input instanceof UntitledTextEditorInput ? basenameOrAuthority(this.input.resource) : this.input?.getName();
if (this.input?.isReadonly()) {
ariaLabel = inputName ? nls.localize('readonlyEditorWithInputAriaLabel', "{0} readonly editor", inputName) : nls.localize('readonlyEditorAriaLabel', "Readonly editor");
} else {
@@ -163,7 +163,7 @@ export class AbstractTextResourceEditor extends BaseTextEditor {
return; // only enabled for untitled and resource inputs
}
const resource = input.getResource();
const resource = input.resource;
// Clear view state if input is disposed
if (input.isDisposed()) {

View File

@@ -23,10 +23,10 @@ export class NotificationsAlerts extends Disposable {
}
private registerListeners(): void {
this._register(this.model.onDidNotificationChange(e => this.onDidNotificationChange(e)));
this._register(this.model.onDidChangeNotification(e => this.onDidChangeNotification(e)));
}
private onDidNotificationChange(e: INotificationChangeEvent): void {
private onDidChangeNotification(e: INotificationChangeEvent): void {
if (e.kind === NotificationChangeType.ADD) {
// ARIA alert for screen readers
@@ -37,7 +37,7 @@ export class NotificationsAlerts extends Disposable {
if (e.item.message.original instanceof Error) {
console.error(e.item.message.original);
} else {
console.error(toErrorMessage(e.item.message.value, true));
console.error(toErrorMessage(e.item.message.linkedText.toString(), true));
}
}
}
@@ -46,7 +46,7 @@ export class NotificationsAlerts extends Disposable {
private triggerAriaAlert(notifiation: INotificationViewItem): void {
// Trigger the alert again whenever the label changes
const listener = notifiation.onDidLabelChange(e => {
const listener = notifiation.onDidChangeLabel(e => {
if (e.kind === NotificationViewItemLabelKind.MESSAGE) {
this.doTriggerAriaAlert(notifiation);
}
@@ -60,13 +60,13 @@ export class NotificationsAlerts extends Disposable {
private doTriggerAriaAlert(notifiation: INotificationViewItem): void {
let alertText: string;
if (notifiation.severity === Severity.Error) {
alertText = localize('alertErrorMessage', "Error: {0}", notifiation.message.value);
alertText = localize('alertErrorMessage', "Error: {0}", notifiation.message.linkedText.toString());
} else if (notifiation.severity === Severity.Warning) {
alertText = localize('alertWarningMessage', "Warning: {0}", notifiation.message.value);
alertText = localize('alertWarningMessage', "Warning: {0}", notifiation.message.linkedText.toString());
} else {
alertText = localize('alertInfoMessage', "Info: {0}", notifiation.message.value);
alertText = localize('alertInfoMessage', "Info: {0}", notifiation.message.linkedText.toString());
}
alert(alertText);
}
}
}

View File

@@ -58,7 +58,7 @@ export class NotificationsCenter extends Themable {
}
private registerListeners(): void {
this._register(this.model.onDidNotificationChange(e => this.onDidNotificationChange(e)));
this._register(this.model.onDidChangeNotification(e => this.onDidChangeNotification(e)));
this._register(this.layoutService.onLayout(dimension => this.layout(dimension)));
}
@@ -167,7 +167,7 @@ export class NotificationsCenter extends Themable {
return keybinding ? keybinding.getLabel() : null;
}
private onDidNotificationChange(e: INotificationChangeEvent): void {
private onDidChangeNotification(e: INotificationChangeEvent): void {
if (!this._isVisible) {
return; // only if visible
}

View File

@@ -181,7 +181,7 @@ export class NotificationsList extends Themable {
}
// Restore DOM focus if we had focus before
if (listHasDOMFocus) {
if (this.isVisible && listHasDOMFocus) {
list.domFocus();
}
}

View File

@@ -34,11 +34,11 @@ export class NotificationsStatus extends Disposable {
}
private registerListeners(): void {
this._register(this.model.onDidNotificationChange(e => this.onDidNotificationChange(e)));
this._register(this.model.onDidStatusMessageChange(e => this.onDidStatusMessageChange(e)));
this._register(this.model.onDidChangeNotification(e => this.onDidChangeNotification(e)));
this._register(this.model.onDidChangeStatusMessage(e => this.onDidChangeStatusMessage(e)));
}
private onDidNotificationChange(e: INotificationChangeEvent): void {
private onDidChangeNotification(e: INotificationChangeEvent): void {
if (this.isNotificationsCenterVisible) {
return; // no change if notification center is visible
}
@@ -101,7 +101,7 @@ export class NotificationsStatus extends Disposable {
}
}
private onDidStatusMessageChange(e: IStatusMessageChangeEvent): void {
private onDidChangeStatusMessage(e: IStatusMessageChangeEvent): void {
const statusItem = e.item;
switch (e.kind) {

View File

@@ -90,11 +90,11 @@ export class NotificationsToasts extends Themable {
this.model.notifications.forEach(notification => this.addToast(notification));
// Update toasts on notification changes
this._register(this.model.onDidNotificationChange(e => this.onDidNotificationChange(e)));
this._register(this.model.onDidChangeNotification(e => this.onDidChangeNotification(e)));
});
// Filter
this._register(this.model.onDidFilterChange(filter => {
this._register(this.model.onDidChangeFilter(filter => {
if (filter === NotificationsFilter.SILENT || filter === NotificationsFilter.ERROR) {
this.hide();
}
@@ -114,7 +114,7 @@ export class NotificationsToasts extends Themable {
]);
}
private onDidNotificationChange(e: INotificationChangeEvent): void {
private onDidChangeNotification(e: INotificationChangeEvent): void {
switch (e.kind) {
case NotificationChangeType.ADD:
return this.addToast(e.item);
@@ -194,12 +194,12 @@ export class NotificationsToasts extends Themable {
this.layoutContainer(maxDimensions.height);
// Update when item height changes due to expansion
itemDisposables.add(item.onDidExpansionChange(() => {
itemDisposables.add(item.onDidChangeExpansion(() => {
notificationList.updateNotificationsList(0, 1, [item]);
}));
// Update when item height potentially changes due to label changes
itemDisposables.add(item.onDidLabelChange(e => {
itemDisposables.add(item.onDidChangeLabel(e => {
if (!item.expanded) {
return; // dynamic height only applies to expanded notifications
}

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { IListVirtualDelegate, IListRenderer } from 'vs/base/browser/ui/list/list';
import { clearNode, addClass, removeClass, toggleClass, addDisposableListener, EventType, EventHelper } from 'vs/base/browser/dom';
import { clearNode, addClass, removeClass, toggleClass, addDisposableListener, EventType, EventHelper, $ } from 'vs/base/browser/dom';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { URI } from 'vs/base/common/uri';
import { localize } from 'vs/nls';
@@ -23,6 +23,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar';
import { Severity } from 'vs/platform/notification/common/notification';
import { isNonEmptyArray } from 'vs/base/common/arrays';
import { startsWith } from 'vs/base/common/strings';
export class NotificationsListDelegate implements IListVirtualDelegate<INotificationViewItem> {
@@ -136,39 +137,25 @@ class NotificationMessageRenderer {
static render(message: INotificationMessage, actionHandler?: IMessageActionHandler): HTMLElement {
const messageContainer = document.createElement('span');
// Message has no links
if (message.links.length === 0) {
messageContainer.textContent = message.value;
}
for (const node of message.linkedText.nodes) {
if (typeof node === 'string') {
messageContainer.appendChild(document.createTextNode(node));
} else {
let title = node.title;
// Message has links
else {
let index = 0;
for (const link of message.links) {
const textBefore = message.value.substring(index, link.offset);
if (textBefore) {
messageContainer.appendChild(document.createTextNode(textBefore));
if (!title && startsWith(node.href, 'command:')) {
title = localize('executeCommand', "Click to execute command '{0}'", node.href.substr('command:'.length));
} else if (!title) {
title = node.href;
}
const anchor = document.createElement('a');
anchor.textContent = link.name;
anchor.title = link.title;
anchor.href = link.href;
const anchor = $('a', { href: node.href, title: title, }, node.label);
if (actionHandler) {
actionHandler.toDispose.add(addDisposableListener(anchor, EventType.CLICK, () => actionHandler.callback(link.href)));
actionHandler.toDispose.add(addDisposableListener(anchor, EventType.CLICK, () => actionHandler.callback(node.href)));
}
messageContainer.appendChild(anchor);
index = link.offset + link.length;
}
// Add text after links if any
const textAfter = message.value.substring(index);
if (textAfter) {
messageContainer.appendChild(document.createTextNode(textAfter));
}
}
@@ -345,7 +332,7 @@ export class NotificationTemplateRenderer extends Disposable {
this.renderProgress(notification);
// Label Change Events
this.inputDisposables.add(notification.onDidLabelChange(event => {
this.inputDisposables.add(notification.onDidChangeLabel(event => {
switch (event.kind) {
case NotificationViewItemLabelKind.SEVERITY:
this.renderSeverity(notification);

View File

@@ -76,7 +76,7 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
//#endregion
get onDidPanelOpen(): Event<{ panel: IPanel, focus: boolean; }> { return Event.map(this.onDidCompositeOpen.event, compositeOpen => ({ panel: compositeOpen.composite, focus: compositeOpen.focus })); }
readonly onDidPanelClose: Event<IPanel> = this.onDidCompositeClose.event;
readonly onDidPanelClose = this.onDidCompositeClose.event;
private activePanelContextKey: IContextKey<string>;
private panelFocusContextKey: IContextKey<boolean>;

View File

@@ -817,7 +817,7 @@ export class EditorHistoryEntry extends EditorQuickOpenEntry {
}
function resourceForEditorHistory(input: EditorInput, fileService: IFileService): URI | undefined {
const resource = input ? input.getResource() : undefined;
const resource = input ? input.resource : undefined;
// For the editor history we only prefer resources that are either untitled or
// can be handled by the file service which indicates they are editable resources.

View File

@@ -71,7 +71,7 @@
display: none;
}
.monaco-workbench .pane > .pane-body > .empty-view {
.monaco-workbench .pane > .pane-body > .welcome-view {
width: 100%;
height: 100%;
padding: 0 20px 0 20px;
@@ -79,12 +79,12 @@
box-sizing: border-box;
}
.monaco-workbench .pane > .pane-body:not(.empty) > .empty-view,
.monaco-workbench .pane > .pane-body.empty > :not(.empty-view) {
.monaco-workbench .pane > .pane-body:not(.welcome) > .welcome-view,
.monaco-workbench .pane > .pane-body.welcome > :not(.welcome-view) {
display: none;
}
.monaco-workbench .pane > .pane-body > .empty-view .monaco-button {
.monaco-workbench .pane > .pane-body > .welcome-view .monaco-button {
max-width: 260px;
margin-left: auto;
margin-right: auto;

View File

@@ -25,7 +25,7 @@ import { PaneView, IPaneViewOptions, IPaneOptions, Pane, DefaultPaneDndControlle
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import { Extensions as ViewContainerExtensions, IView, FocusedViewContext, IViewContainersRegistry, IViewDescriptor, ViewContainer, IViewDescriptorService, ViewContainerLocation, IViewPaneContainer, IViewsRegistry } from 'vs/workbench/common/views';
import { Extensions as ViewContainerExtensions, IView, FocusedViewContext, IViewContainersRegistry, IViewDescriptor, ViewContainer, IViewDescriptorService, ViewContainerLocation, IViewPaneContainer, IViewsRegistry, IViewContentDescriptor } from 'vs/workbench/common/views';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { assertIsDefined } from 'vs/base/common/types';
@@ -38,7 +38,7 @@ import { Component } from 'vs/workbench/common/component';
import { MenuId, MenuItemAction } from 'vs/platform/actions/common/actions';
import { ContextAwareMenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { ViewMenuActions } from 'vs/workbench/browser/parts/views/viewMenuActions';
import { parseLinkedText } from 'vs/base/browser/linkedText';
import { parseLinkedText } from 'vs/base/common/linkedText';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { Button } from 'vs/base/browser/ui/button/button';
import { Link } from 'vs/platform/opener/browser/link';
@@ -60,6 +60,88 @@ export interface IViewPaneOptions extends IPaneOptions {
const viewsRegistry = Registry.as<IViewsRegistry>(ViewContainerExtensions.ViewsRegistry);
interface IItem {
readonly descriptor: IViewContentDescriptor;
visible: boolean;
}
class ViewWelcomeController {
private _onDidChange = new Emitter<void>();
readonly onDidChange = this._onDidChange.event;
private defaultItem: IItem | undefined;
private items: IItem[] = [];
get contents(): IViewContentDescriptor[] {
const visibleItems = this.items.filter(v => v.visible);
if (visibleItems.length === 0 && this.defaultItem) {
return [this.defaultItem.descriptor];
}
return visibleItems.map(v => v.descriptor);
}
private contextKeyService: IContextKeyService;
private disposables = new DisposableStore();
constructor(
private id: string,
@IContextKeyService contextKeyService: IContextKeyService,
) {
this.contextKeyService = contextKeyService.createScoped();
this.disposables.add(this.contextKeyService);
contextKeyService.onDidChangeContext(this.onDidChangeContext, this, this.disposables);
Event.filter(viewsRegistry.onDidChangeViewWelcomeContent, id => id === this.id)(this.onDidChangeViewWelcomeContent, this, this.disposables);
this.onDidChangeViewWelcomeContent();
}
private onDidChangeViewWelcomeContent(): void {
const descriptors = viewsRegistry.getViewWelcomeContent(this.id);
this.items = [];
for (const descriptor of descriptors) {
if (descriptor.when === 'default') {
this.defaultItem = { descriptor, visible: true };
} else {
const visible = descriptor.when ? this.contextKeyService.contextMatchesRules(descriptor.when) : true;
this.items.push({ descriptor, visible });
}
}
this._onDidChange.fire();
}
private onDidChangeContext(): void {
let didChange = false;
for (const item of this.items) {
if (!item.descriptor.when || item.descriptor.when === 'default') {
continue;
}
const visible = this.contextKeyService.contextMatchesRules(item.descriptor.when);
if (item.visible === visible) {
continue;
}
item.visible = visible;
didChange = true;
}
if (didChange) {
this._onDidChange.fire();
}
}
dispose(): void {
this.disposables.dispose();
}
}
export abstract class ViewPane extends Pane implements IView {
private static readonly AlwaysShowActionsConfig = 'workbench.view.alwaysShowHeaderActions';
@@ -76,8 +158,8 @@ export abstract class ViewPane extends Pane implements IView {
protected _onDidChangeTitleArea = this._register(new Emitter<void>());
readonly onDidChangeTitleArea: Event<void> = this._onDidChangeTitleArea.event;
protected _onDidChangeEmptyState = this._register(new Emitter<void>());
readonly onDidChangeEmptyState: Event<void> = this._onDidChangeEmptyState.event;
protected _onDidChangeViewWelcomeState = this._register(new Emitter<void>());
readonly onDidChangeViewWelcomeState: Event<void> = this._onDidChangeViewWelcomeState.event;
private focusedViewContextKey: IContextKey<string>;
@@ -95,8 +177,9 @@ export abstract class ViewPane extends Pane implements IView {
protected twistiesContainer?: HTMLElement;
private bodyContainer!: HTMLElement;
private emptyViewContainer!: HTMLElement;
private emptyViewDisposable: IDisposable = Disposable.None;
private viewWelcomeContainer!: HTMLElement;
private viewWelcomeDisposable: IDisposable = Disposable.None;
private viewWelcomeController: ViewWelcomeController;
constructor(
options: IViewPaneOptions,
@@ -119,6 +202,8 @@ export abstract class ViewPane extends Pane implements IView {
this.menuActions = this._register(instantiationService.createInstance(ViewMenuActions, this.id, options.titleMenuId || MenuId.ViewTitle, MenuId.ViewTitleContext));
this._register(this.menuActions.onDidChangeTitle(() => this.updateActions()));
this.viewWelcomeController = new ViewWelcomeController(this.id, contextKeyService);
}
setVisible(visible: boolean): void {
@@ -206,18 +291,15 @@ export abstract class ViewPane extends Pane implements IView {
protected renderBody(container: HTMLElement): void {
this.bodyContainer = container;
this.emptyViewContainer = append(container, $('.empty-view', { tabIndex: 0 }));
this.viewWelcomeContainer = append(container, $('.welcome-view', { tabIndex: 0 }));
// we should update our empty state whenever
const onEmptyViewContentChange = Event.any(
// the registry changes
Event.map(Event.filter(viewsRegistry.onDidChangeEmptyViewContent, id => id === this.id), () => this.isEmpty()),
// or the view's empty state changes
Event.latch(Event.map(this.onDidChangeEmptyState, () => this.isEmpty()))
);
const onViewWelcomeChange = Event.any(this.viewWelcomeController.onDidChange, this.onDidChangeViewWelcomeState);
this._register(onViewWelcomeChange(this.updateViewWelcome, this));
this.updateViewWelcome();
}
this._register(onEmptyViewContentChange(this.updateEmptyState, this));
this.updateEmptyState(this.isEmpty());
protected layoutBody(height: number, width: number): void {
// noop
}
protected getProgressLocation(): string {
@@ -286,26 +368,26 @@ export abstract class ViewPane extends Pane implements IView {
// Subclasses to implement for saving state
}
private updateEmptyState(isEmpty: boolean): void {
this.emptyViewDisposable.dispose();
private updateViewWelcome(): void {
this.viewWelcomeDisposable.dispose();
if (!isEmpty) {
removeClass(this.bodyContainer, 'empty');
this.emptyViewContainer.innerHTML = '';
if (!this.shouldShowWelcome()) {
removeClass(this.bodyContainer, 'welcome');
this.viewWelcomeContainer.innerHTML = '';
return;
}
const contents = viewsRegistry.getEmptyViewContent(this.id);
const contents = this.viewWelcomeController.contents;
if (contents.length === 0) {
removeClass(this.bodyContainer, 'empty');
this.emptyViewContainer.innerHTML = '';
removeClass(this.bodyContainer, 'welcome');
this.viewWelcomeContainer.innerHTML = '';
return;
}
const disposables = new DisposableStore();
addClass(this.bodyContainer, 'empty');
this.emptyViewContainer.innerHTML = '';
addClass(this.bodyContainer, 'welcome');
this.viewWelcomeContainer.innerHTML = '';
for (const { content } of contents) {
const lines = content.split('\n');
@@ -317,13 +399,13 @@ export abstract class ViewPane extends Pane implements IView {
continue;
}
const p = append(this.emptyViewContainer, $('p'));
const p = append(this.viewWelcomeContainer, $('p'));
const linkedText = parseLinkedText(line);
for (const node of linkedText) {
for (const node of linkedText.nodes) {
if (typeof node === 'string') {
append(p, document.createTextNode(node));
} else if (linkedText.length === 1) {
} else if (linkedText.nodes.length === 1) {
const button = new Button(p, { title: node.title });
button.label = node.label;
button.onDidClick(_ => this.openerService.open(node.href), null, disposables);
@@ -339,10 +421,10 @@ export abstract class ViewPane extends Pane implements IView {
}
}
this.emptyViewDisposable = disposables;
this.viewWelcomeDisposable = disposables;
}
isEmpty(): boolean {
shouldShowWelcome(): boolean {
return false;
}
}

View File

@@ -68,7 +68,7 @@ export abstract class Viewlet extends PaneComposite implements IViewlet {
*/
export class ViewletDescriptor extends CompositeDescriptor<Viewlet> {
public static create<Services extends BrandedService[]>(
static create<Services extends BrandedService[]>(
ctor: { new(...services: Services): Viewlet },
id: string,
name: string,

View File

@@ -41,7 +41,6 @@ import { joinPath } from 'vs/base/common/resources';
import { BrowserStorageService } from 'vs/platform/storage/browser/storageService';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { getThemeTypeSelector, DARK, HIGH_CONTRAST, LIGHT } from 'vs/platform/theme/common/themeService';
import { InMemoryFileSystemProvider } from 'vs/workbench/services/userData/common/inMemoryUserDataProvider';
import { registerWindowDriver } from 'vs/platform/driver/browser/driver';
import { BufferLogService } from 'vs/platform/log/common/bufferLog';
import { FileLogService } from 'vs/platform/log/common/fileLogService';
@@ -51,6 +50,7 @@ import { InMemoryLogProvider } from 'vs/workbench/services/log/common/inMemoryLo
import { isWorkspaceToOpen, isFolderToOpen } from 'vs/platform/windows/common/windows';
import { getWorkspaceIdentifier } from 'vs/workbench/services/workspaces/browser/workspaces';
import { coalesce } from 'vs/base/common/arrays';
import { InMemoryFileSystemProvider } from 'vs/platform/files/common/inMemoryFilesystemProvider';
class BrowserMain extends Disposable {

View File

@@ -6,7 +6,7 @@
import 'vs/workbench/browser/style';
import { localize } from 'vs/nls';
import { Event, Emitter, setGlobalLeakWarningThreshold } from 'vs/base/common/event';
import { Emitter, setGlobalLeakWarningThreshold } from 'vs/base/common/event';
import { addClasses, addClass, removeClasses } from 'vs/base/browser/dom';
import { runWhenIdle } from 'vs/base/common/async';
import { getZoomLevel, isFirefox, isSafari, isChrome } from 'vs/base/browser/browser';
@@ -51,13 +51,13 @@ import { Extensions as PanelExtensions, PanelRegistry } from 'vs/workbench/brows
export class Workbench extends Layout {
private readonly _onBeforeShutdown = this._register(new Emitter<BeforeShutdownEvent>());
readonly onBeforeShutdown: Event<BeforeShutdownEvent> = this._onBeforeShutdown.event;
readonly onBeforeShutdown = this._onBeforeShutdown.event;
private readonly _onWillShutdown = this._register(new Emitter<WillShutdownEvent>());
readonly onWillShutdown: Event<WillShutdownEvent> = this._onWillShutdown.event;
readonly onWillShutdown = this._onWillShutdown.event;
private readonly _onShutdown = this._register(new Emitter<void>());
readonly onShutdown: Event<void> = this._onShutdown.event;
readonly onShutdown = this._onShutdown.event;
constructor(
parent: HTMLElement,