mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-03-31 01:00: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:
@@ -8,7 +8,7 @@ import { EditorInput, EditorOptions, IEditor, GroupIdentifier, IEditorMemento }
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
|
||||
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
import { LRUCache } from 'vs/base/common/map';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
|
||||
@@ -11,7 +11,7 @@ import { localize } from 'vs/nls';
|
||||
import { IConfigurationOverrides, IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { GroupIdentifier } from 'vs/workbench/common/editor';
|
||||
|
||||
@@ -19,7 +19,7 @@ export const IBreadcrumbsService = createDecorator<IBreadcrumbsService>('IEditor
|
||||
|
||||
export interface IBreadcrumbsService {
|
||||
|
||||
_serviceBrand: any;
|
||||
_serviceBrand: ServiceIdentifier<any>;
|
||||
|
||||
register(group: GroupIdentifier, widget: BreadcrumbsWidget): IDisposable;
|
||||
|
||||
@@ -29,7 +29,7 @@ export interface IBreadcrumbsService {
|
||||
|
||||
export class BreadcrumbsService implements IBreadcrumbsService {
|
||||
|
||||
_serviceBrand: any;
|
||||
_serviceBrand: ServiceIdentifier<any>;
|
||||
|
||||
private readonly _map = new Map<number, BreadcrumbsWidget>();
|
||||
|
||||
|
||||
@@ -41,10 +41,12 @@ import { BreadcrumbElement, EditorBreadcrumbsModel, FileElement } from 'vs/workb
|
||||
import { BreadcrumbsPicker, createBreadcrumbsPicker } from 'vs/workbench/browser/parts/editor/breadcrumbsPicker';
|
||||
import { SideBySideEditorInput } from 'vs/workbench/common/editor';
|
||||
import { ACTIVE_GROUP, ACTIVE_GROUP_TYPE, IEditorService, SIDE_GROUP, SIDE_GROUP_TYPE } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
|
||||
import { IEditorGroupView } from 'vs/workbench/browser/parts/editor/editor';
|
||||
import { onDidChangeZoomLevel } from 'vs/base/browser/browser';
|
||||
import { withNullAsUndefined, withUndefinedAsNull } from 'vs/base/common/types';
|
||||
|
||||
class Item extends BreadcrumbsItem {
|
||||
|
||||
@@ -148,6 +150,7 @@ export class BreadcrumbsControl {
|
||||
private _disposables = new Array<IDisposable>();
|
||||
private _breadcrumbsDisposables = new Array<IDisposable>();
|
||||
private _breadcrumbsPickerShowing = false;
|
||||
private _breadcrumbsPickerIgnoreOnceItem: BreadcrumbsItem | undefined;
|
||||
|
||||
constructor(
|
||||
container: HTMLElement,
|
||||
@@ -196,7 +199,7 @@ export class BreadcrumbsControl {
|
||||
this.domNode.remove();
|
||||
}
|
||||
|
||||
layout(dim: dom.Dimension): void {
|
||||
layout(dim: dom.Dimension | undefined): void {
|
||||
this._widget.layout(dim);
|
||||
}
|
||||
|
||||
@@ -219,7 +222,7 @@ export class BreadcrumbsControl {
|
||||
input = input.master;
|
||||
}
|
||||
|
||||
if (!input || !input.getResource() || (input.getResource().scheme !== Schemas.untitled && !this._fileService.canHandleResource(input.getResource()))) {
|
||||
if (!input || !input.getResource() || (input.getResource()!.scheme !== Schemas.untitled && !this._fileService.canHandleResource(input.getResource()!))) {
|
||||
// cleanup and return when there is no input or when
|
||||
// we cannot handle this input
|
||||
this._ckBreadcrumbsPossible.set(false);
|
||||
@@ -236,7 +239,7 @@ export class BreadcrumbsControl {
|
||||
this._ckBreadcrumbsPossible.set(true);
|
||||
|
||||
let editor = this._getActiveCodeEditor();
|
||||
let model = new EditorBreadcrumbsModel(input.getResource(), editor, this._workspaceService, this._configurationService);
|
||||
let model = new EditorBreadcrumbsModel(input.getResource()!, editor, this._workspaceService, this._configurationService);
|
||||
dom.toggleClass(this.domNode, 'relative-path', model.isRelative());
|
||||
|
||||
let updateBreadcrumbs = () => {
|
||||
@@ -260,9 +263,12 @@ export class BreadcrumbsControl {
|
||||
return true;
|
||||
}
|
||||
|
||||
private _getActiveCodeEditor(): ICodeEditor {
|
||||
private _getActiveCodeEditor(): ICodeEditor | undefined {
|
||||
if (!this._editorGroup.activeControl) {
|
||||
return undefined;
|
||||
}
|
||||
let control = this._editorGroup.activeControl.getControl();
|
||||
let editor: ICodeEditor;
|
||||
let editor: ICodeEditor | undefined;
|
||||
if (isCodeEditor(control)) {
|
||||
editor = control as ICodeEditor;
|
||||
} else if (isDiffEditor(control)) {
|
||||
@@ -282,6 +288,13 @@ export class BreadcrumbsControl {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.item === this._breadcrumbsPickerIgnoreOnceItem) {
|
||||
this._breadcrumbsPickerIgnoreOnceItem = undefined;
|
||||
this._widget.setFocused(undefined);
|
||||
this._widget.setSelection(undefined);
|
||||
return;
|
||||
}
|
||||
|
||||
const { element } = event.item as Item;
|
||||
this._editorGroup.focus();
|
||||
|
||||
@@ -313,7 +326,7 @@ export class BreadcrumbsControl {
|
||||
let picker: BreadcrumbsPicker;
|
||||
let editor = this._getActiveCodeEditor();
|
||||
let editorDecorations: string[] = [];
|
||||
let editorViewState: ICodeEditorViewState;
|
||||
let editorViewState: ICodeEditorViewState | undefined;
|
||||
|
||||
this._contextViewService.showContextView({
|
||||
render: (parent: HTMLElement) => {
|
||||
@@ -336,7 +349,7 @@ export class BreadcrumbsControl {
|
||||
return;
|
||||
}
|
||||
if (!editorViewState) {
|
||||
editorViewState = editor.saveViewState();
|
||||
editorViewState = withNullAsUndefined(editor.saveViewState());
|
||||
}
|
||||
const { symbol } = data.target;
|
||||
editor.revealRangeInCenter(symbol.range, ScrollType.Smooth);
|
||||
@@ -347,12 +360,29 @@ export class BreadcrumbsControl {
|
||||
isWholeLine: true
|
||||
}
|
||||
}]);
|
||||
|
||||
});
|
||||
|
||||
let zoomListener = onDidChangeZoomLevel(() => {
|
||||
this._contextViewService.hideContextView(this);
|
||||
});
|
||||
|
||||
let focusTracker = dom.trackFocus(parent);
|
||||
let blurListener = focusTracker.onDidBlur(() => {
|
||||
this._breadcrumbsPickerIgnoreOnceItem = this._widget.isDOMFocused() ? event.item : undefined;
|
||||
this._contextViewService.hideContextView(this);
|
||||
});
|
||||
|
||||
this._breadcrumbsPickerShowing = true;
|
||||
this._updateCkBreadcrumbsActive();
|
||||
|
||||
return combinedDisposable([selectListener, focusListener, picker]);
|
||||
return combinedDisposable([
|
||||
picker,
|
||||
selectListener,
|
||||
focusListener,
|
||||
zoomListener,
|
||||
focusTracker,
|
||||
blurListener
|
||||
]);
|
||||
},
|
||||
getAnchor: () => {
|
||||
let maxInnerWidth = window.innerWidth - 8 /*a little less the full widget*/;
|
||||
@@ -381,7 +411,7 @@ export class BreadcrumbsControl {
|
||||
} else {
|
||||
pickerArrowOffset = (data.left + (data.width * 0.3)) - x;
|
||||
}
|
||||
picker.setInput(element, maxHeight, pickerWidth, pickerArrowSize, Math.max(0, pickerArrowOffset));
|
||||
picker.show(element, maxHeight, pickerWidth, pickerArrowSize, Math.max(0, pickerArrowOffset));
|
||||
return { x, y };
|
||||
},
|
||||
onHide: (data) => {
|
||||
@@ -406,7 +436,7 @@ export class BreadcrumbsControl {
|
||||
this._ckBreadcrumbsActive.set(value);
|
||||
}
|
||||
|
||||
private _revealInEditor(event: IBreadcrumbsItemEvent, element: any, group: SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE, pinned: boolean = false): void {
|
||||
private _revealInEditor(event: IBreadcrumbsItemEvent, element: any, group: SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE | undefined, pinned: boolean = false): void {
|
||||
if (element instanceof FileElement) {
|
||||
if (element.kind === FileKind.FILE) {
|
||||
// open file in any editor
|
||||
@@ -421,14 +451,16 @@ export class BreadcrumbsControl {
|
||||
|
||||
} else if (element instanceof OutlineElement) {
|
||||
// open symbol in code editor
|
||||
let model = OutlineModel.get(element);
|
||||
this._codeEditorService.openCodeEditor({
|
||||
resource: model.textModel.uri,
|
||||
options: {
|
||||
selection: Range.collapseToStart(element.symbol.selectionRange),
|
||||
revealInCenterIfOutsideViewport: true
|
||||
}
|
||||
}, this._getActiveCodeEditor(), group === SIDE_GROUP);
|
||||
const model = OutlineModel.get(element);
|
||||
if (model) {
|
||||
this._codeEditorService.openCodeEditor({
|
||||
resource: model.textModel.uri,
|
||||
options: {
|
||||
selection: Range.collapseToStart(element.symbol.selectionRange),
|
||||
revealInCenterIfOutsideViewport: true
|
||||
}
|
||||
}, withUndefinedAsNull(this._getActiveCodeEditor()), group === SIDE_GROUP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -449,7 +481,7 @@ export class BreadcrumbsControl {
|
||||
MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
|
||||
command: {
|
||||
id: 'breadcrumbs.toggle',
|
||||
title: { value: localize('cmd.toggle', "Toggle Breadcrumbs"), original: 'Toggle Breadcrumbs' },
|
||||
title: { value: localize('cmd.toggle', "Toggle Breadcrumbs"), original: 'View: Toggle Breadcrumbs' },
|
||||
category: localize('cmd.category', "View")
|
||||
}
|
||||
});
|
||||
@@ -540,7 +572,11 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
handler(accessor) {
|
||||
const groups = accessor.get(IEditorGroupsService);
|
||||
const breadcrumbs = accessor.get(IBreadcrumbsService);
|
||||
breadcrumbs.getWidget(groups.activeGroup.id).focusNext();
|
||||
const widget = breadcrumbs.getWidget(groups.activeGroup.id);
|
||||
if (!widget) {
|
||||
return;
|
||||
}
|
||||
widget.focusNext();
|
||||
}
|
||||
});
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
@@ -556,7 +592,11 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
handler(accessor) {
|
||||
const groups = accessor.get(IEditorGroupsService);
|
||||
const breadcrumbs = accessor.get(IBreadcrumbsService);
|
||||
breadcrumbs.getWidget(groups.activeGroup.id).focusPrev();
|
||||
const widget = breadcrumbs.getWidget(groups.activeGroup.id);
|
||||
if (!widget) {
|
||||
return;
|
||||
}
|
||||
widget.focusPrev();
|
||||
}
|
||||
});
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
@@ -569,6 +609,9 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
const groups = accessor.get(IEditorGroupsService);
|
||||
const breadcrumbs = accessor.get(IBreadcrumbsService);
|
||||
const widget = breadcrumbs.getWidget(groups.activeGroup.id);
|
||||
if (!widget) {
|
||||
return;
|
||||
}
|
||||
widget.setSelection(widget.getFocused(), BreadcrumbsControl.Payload_Pick);
|
||||
}
|
||||
});
|
||||
@@ -582,6 +625,9 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
const groups = accessor.get(IEditorGroupsService);
|
||||
const breadcrumbs = accessor.get(IBreadcrumbsService);
|
||||
const widget = breadcrumbs.getWidget(groups.activeGroup.id);
|
||||
if (!widget) {
|
||||
return;
|
||||
}
|
||||
widget.setSelection(widget.getFocused(), BreadcrumbsControl.Payload_Reveal);
|
||||
}
|
||||
});
|
||||
@@ -593,9 +639,15 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
handler(accessor) {
|
||||
const groups = accessor.get(IEditorGroupsService);
|
||||
const breadcrumbs = accessor.get(IBreadcrumbsService);
|
||||
breadcrumbs.getWidget(groups.activeGroup.id).setFocused(undefined);
|
||||
breadcrumbs.getWidget(groups.activeGroup.id).setSelection(undefined);
|
||||
groups.activeGroup.activeControl.focus();
|
||||
const widget = breadcrumbs.getWidget(groups.activeGroup.id);
|
||||
if (!widget) {
|
||||
return;
|
||||
}
|
||||
widget.setFocused(undefined);
|
||||
widget.setSelection(undefined);
|
||||
if (groups.activeGroup.activeControl) {
|
||||
groups.activeGroup.activeControl.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
@@ -606,15 +658,20 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
handler(accessor) {
|
||||
const editors = accessor.get(IEditorService);
|
||||
const lists = accessor.get(IListService);
|
||||
const element = <OutlineElement | IFileStat>lists.lastFocusedList.getFocus();
|
||||
const element = lists.lastFocusedList ? <OutlineElement | IFileStat>lists.lastFocusedList.getFocus() : undefined;
|
||||
if (element instanceof OutlineElement) {
|
||||
const outlineElement = OutlineModel.get(element);
|
||||
if (!outlineElement) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// open symbol in editor
|
||||
return editors.openEditor({
|
||||
resource: OutlineModel.get(element).textModel.uri,
|
||||
resource: outlineElement.textModel.uri,
|
||||
options: { selection: Range.collapseToStart(element.symbol.selectionRange) }
|
||||
}, SIDE_GROUP);
|
||||
|
||||
} else if (URI.isUri(element.resource)) {
|
||||
} else if (element && URI.isUri(element.resource)) {
|
||||
// open file in editor
|
||||
return editors.openEditor({
|
||||
resource: element.resource,
|
||||
|
||||
@@ -21,6 +21,7 @@ import { Schemas } from 'vs/base/common/network';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { BreadcrumbsConfig } from 'vs/workbench/browser/parts/editor/breadcrumbs';
|
||||
import { FileKind } from 'vs/platform/files/common/files';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
|
||||
export class FileElement {
|
||||
constructor(
|
||||
@@ -105,7 +106,7 @@ export class EditorBreadcrumbsModel {
|
||||
}
|
||||
|
||||
let info: FileInfo = {
|
||||
folder: workspaceService.getWorkspaceFolder(uri) || undefined,
|
||||
folder: withNullAsUndefined(workspaceService.getWorkspaceFolder(uri)),
|
||||
path: []
|
||||
};
|
||||
|
||||
@@ -117,7 +118,7 @@ export class EditorBreadcrumbsModel {
|
||||
info.path.unshift(new FileElement(uriPrefix, info.path.length === 0 ? FileKind.FILE : FileKind.FOLDER));
|
||||
let prevPathLength = uriPrefix.path.length;
|
||||
uriPrefix = dirname(uriPrefix);
|
||||
if (!uriPrefix || uriPrefix.path.length === prevPathLength) {
|
||||
if (uriPrefix.path.length === prevPathLength) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,35 +3,38 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { onDidChangeZoomLevel } from 'vs/base/browser/browser';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { compareFileNames } from 'vs/base/common/comparers';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { createMatches, FuzzyScore, fuzzyScore } from 'vs/base/common/filters';
|
||||
import { createMatches, FuzzyScore } from 'vs/base/common/filters';
|
||||
import * as glob from 'vs/base/common/glob';
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { join } from 'vs/base/common/paths';
|
||||
import { posix } from 'vs/base/common/path';
|
||||
import { basename, dirname, isEqual } from 'vs/base/common/resources';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IDataSource, IFilter, IRenderer, ISorter, ITree } from 'vs/base/parts/tree/browser/tree';
|
||||
import 'vs/css!./media/breadcrumbscontrol';
|
||||
import { OutlineElement, OutlineModel, TreeElement } from 'vs/editor/contrib/documentSymbols/outlineModel';
|
||||
import { OutlineDataSource, OutlineItemComparator, OutlineRenderer, OutlineItemCompareType } from 'vs/editor/contrib/documentSymbols/outlineTree';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
import { FileKind, IFileService, IFileStat } from 'vs/platform/files/common/files';
|
||||
import { IConstructorSignature1, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { HighlightingWorkbenchTree, IHighlighter, IHighlightingTreeConfiguration, IHighlightingTreeOptions } from 'vs/platform/list/browser/listService';
|
||||
import { WorkbenchDataTree, WorkbenchAsyncDataTree } from 'vs/platform/list/browser/listService';
|
||||
import { breadcrumbsPickerBackground, widgetShadow } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { IWorkspace, IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { ResourceLabels, IResourceLabel, DEFAULT_LABELS_CONTAINER } from 'vs/workbench/browser/labels';
|
||||
import { BreadcrumbsConfig } from 'vs/workbench/browser/parts/editor/breadcrumbs';
|
||||
import { BreadcrumbElement, FileElement } from 'vs/workbench/browser/parts/editor/breadcrumbsModel';
|
||||
import { IFileIconTheme, IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
||||
import { IAsyncDataSource, ITreeRenderer, ITreeNode, ITreeFilter, TreeVisibility, ITreeSorter, IDataSource } from 'vs/base/browser/ui/tree/tree';
|
||||
import { OutlineVirtualDelegate, OutlineGroupRenderer, OutlineElementRenderer, OutlineItemComparator, OutlineIdentityProvider, OutlineNavigationLabelProvider, OutlineDataSource, OutlineSortOrder, OutlineItem } from 'vs/editor/contrib/documentSymbols/outlineTree';
|
||||
import { IIdentityProvider, IListVirtualDelegate, IKeyboardNavigationLabelProvider } from 'vs/base/browser/ui/list/list';
|
||||
import { IDataTreeOptions } from 'vs/base/browser/ui/tree/dataTree';
|
||||
|
||||
export function createBreadcrumbsPicker(instantiationService: IInstantiationService, parent: HTMLElement, element: BreadcrumbElement): BreadcrumbsPicker {
|
||||
let ctor: IConstructorSignature1<HTMLElement, BreadcrumbsPicker> = element instanceof FileElement ? BreadcrumbsFilePicker : BreadcrumbsOutlinePicker;
|
||||
const ctor: IConstructorSignature1<HTMLElement, BreadcrumbsPicker> = element instanceof FileElement
|
||||
? BreadcrumbsFilePicker
|
||||
: BreadcrumbsOutlinePicker;
|
||||
|
||||
return instantiationService.createInstance(ctor, parent);
|
||||
}
|
||||
|
||||
@@ -43,16 +46,17 @@ interface ILayoutInfo {
|
||||
inputHeight: number;
|
||||
}
|
||||
|
||||
type Tree<I, E> = WorkbenchDataTree<I, E, FuzzyScore> | WorkbenchAsyncDataTree<I, E, FuzzyScore>;
|
||||
|
||||
export abstract class BreadcrumbsPicker {
|
||||
|
||||
protected readonly _disposables = new Array<IDisposable>();
|
||||
protected readonly _domNode: HTMLDivElement;
|
||||
protected readonly _arrow: HTMLDivElement;
|
||||
protected readonly _treeContainer: HTMLDivElement;
|
||||
protected readonly _tree: HighlightingWorkbenchTree;
|
||||
protected readonly _focus: dom.IFocusTracker;
|
||||
protected readonly _symbolSortOrder: BreadcrumbsConfig<'position' | 'name' | 'type'>;
|
||||
private _layoutInfo: ILayoutInfo;
|
||||
protected _arrow: HTMLDivElement;
|
||||
protected _treeContainer: HTMLDivElement;
|
||||
protected _tree: Tree<any, any>;
|
||||
protected _fakeEvent = new UIEvent('fakeEvent');
|
||||
protected _layoutInfo: ILayoutInfo;
|
||||
|
||||
private readonly _onDidPickElement = new Emitter<{ target: any, payload: any }>();
|
||||
readonly onDidPickElement: Event<{ target: any, payload: any }> = this._onDidPickElement.event;
|
||||
@@ -64,154 +68,111 @@ export abstract class BreadcrumbsPicker {
|
||||
parent: HTMLElement,
|
||||
@IInstantiationService protected readonly _instantiationService: IInstantiationService,
|
||||
@IWorkbenchThemeService protected readonly _themeService: IWorkbenchThemeService,
|
||||
@IConfigurationService private readonly _configurationService: IConfigurationService,
|
||||
@IConfigurationService protected readonly _configurationService: IConfigurationService,
|
||||
) {
|
||||
this._domNode = document.createElement('div');
|
||||
this._domNode.className = 'monaco-breadcrumbs-picker show-file-icons';
|
||||
parent.appendChild(this._domNode);
|
||||
|
||||
this._focus = dom.trackFocus(this._domNode);
|
||||
this._focus.onDidBlur(_ => this._onDidPickElement.fire({ target: undefined, payload: undefined }), undefined, this._disposables);
|
||||
this._disposables.push(onDidChangeZoomLevel(_ => this._onDidPickElement.fire({ target: undefined, payload: undefined })));
|
||||
|
||||
const theme = this._themeService.getTheme();
|
||||
const color = theme.getColor(breadcrumbsPickerBackground);
|
||||
|
||||
this._arrow = document.createElement('div');
|
||||
this._arrow.className = 'arrow';
|
||||
this._arrow.style.borderColor = `transparent transparent ${color.toString()}`;
|
||||
this._domNode.appendChild(this._arrow);
|
||||
|
||||
this._treeContainer = document.createElement('div');
|
||||
this._treeContainer.style.background = color.toString();
|
||||
this._treeContainer.style.paddingTop = '2px';
|
||||
this._treeContainer.style.boxShadow = `0px 5px 8px ${this._themeService.getTheme().getColor(widgetShadow)}`;
|
||||
this._domNode.appendChild(this._treeContainer);
|
||||
|
||||
this._symbolSortOrder = BreadcrumbsConfig.SymbolSortOrder.bindTo(this._configurationService);
|
||||
|
||||
const filterConfig = BreadcrumbsConfig.FilterOnType.bindTo(this._configurationService);
|
||||
this._disposables.push(filterConfig);
|
||||
|
||||
const treeConfig = this._completeTreeConfiguration({ dataSource: undefined, renderer: undefined, highlighter: undefined });
|
||||
this._tree = this._instantiationService.createInstance(
|
||||
HighlightingWorkbenchTree,
|
||||
this._treeContainer,
|
||||
treeConfig,
|
||||
<IHighlightingTreeOptions>{ useShadows: false, filterOnType: filterConfig.getValue(), showTwistie: false, twistiePixels: 12 },
|
||||
{ placeholder: localize('placeholder', "Find") }
|
||||
);
|
||||
this._disposables.push(this._tree.onDidChangeSelection(e => {
|
||||
if (e.payload !== this._tree) {
|
||||
const target = this._getTargetFromEvent(e.selection[0], e.payload);
|
||||
if (target) {
|
||||
setTimeout(_ => {// need to debounce here because this disposes the tree and the tree doesn't like to be disposed on click
|
||||
this._onDidPickElement.fire({ target, payload: e.payload });
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
}));
|
||||
this._disposables.push(this._tree.onDidChangeFocus(e => {
|
||||
const target = this._getTargetFromEvent(e.focus, e.payload);
|
||||
if (target) {
|
||||
this._onDidFocusElement.fire({ target, payload: e.payload });
|
||||
}
|
||||
}));
|
||||
this._disposables.push(this._tree.onDidStartFiltering(() => {
|
||||
this._layoutInfo.inputHeight = 36;
|
||||
this._layout();
|
||||
}));
|
||||
this._disposables.push(this._tree.onDidExpandItem(() => {
|
||||
this._layout();
|
||||
}));
|
||||
this._disposables.push(this._tree.onDidCollapseItem(() => {
|
||||
this._layout();
|
||||
}));
|
||||
|
||||
// tree icon theme specials
|
||||
dom.addClass(this._treeContainer, 'file-icon-themable-tree');
|
||||
dom.addClass(this._treeContainer, 'show-file-icons');
|
||||
const onFileIconThemeChange = (fileIconTheme: IFileIconTheme) => {
|
||||
dom.toggleClass(this._treeContainer, 'align-icons-and-twisties', fileIconTheme.hasFileIcons && !fileIconTheme.hasFolderIcons);
|
||||
dom.toggleClass(this._treeContainer, 'hide-arrows', fileIconTheme.hidesExplorerArrows === true);
|
||||
};
|
||||
this._disposables.push(_themeService.onDidFileIconThemeChange(onFileIconThemeChange));
|
||||
onFileIconThemeChange(_themeService.getFileIconTheme());
|
||||
|
||||
this._domNode.focus();
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
dispose(this._disposables);
|
||||
this._onDidPickElement.dispose();
|
||||
this._tree.dispose();
|
||||
this._focus.dispose();
|
||||
this._symbolSortOrder.dispose();
|
||||
}
|
||||
|
||||
setInput(input: any, maxHeight: number, width: number, arrowSize: number, arrowOffset: number): void {
|
||||
let actualInput = this._getInput(input);
|
||||
this._tree.setInput(actualInput).then(() => {
|
||||
show(input: any, maxHeight: number, width: number, arrowSize: number, arrowOffset: number): void {
|
||||
|
||||
this._layoutInfo = { maxHeight, width, arrowSize, arrowOffset, inputHeight: 0 };
|
||||
this._layout();
|
||||
const theme = this._themeService.getTheme();
|
||||
const color = theme.getColor(breadcrumbsPickerBackground);
|
||||
|
||||
// use proper selection, reveal
|
||||
let selection = this._getInitialSelection(this._tree, input);
|
||||
if (selection) {
|
||||
return this._tree.reveal(selection, 0.5).then(() => {
|
||||
this._tree.setSelection([selection], this._tree);
|
||||
this._tree.setFocus(selection);
|
||||
this._tree.domFocus();
|
||||
});
|
||||
} else {
|
||||
this._tree.focusFirst();
|
||||
this._tree.setSelection([this._tree.getFocus()], this._tree);
|
||||
this._tree.domFocus();
|
||||
return Promise.resolve(null);
|
||||
this._arrow = document.createElement('div');
|
||||
this._arrow.className = 'arrow';
|
||||
this._arrow.style.borderColor = `transparent transparent ${color ? color.toString() : ''}`;
|
||||
this._domNode.appendChild(this._arrow);
|
||||
|
||||
this._treeContainer = document.createElement('div');
|
||||
this._treeContainer.style.background = color ? color.toString() : '';
|
||||
this._treeContainer.style.paddingTop = '2px';
|
||||
this._treeContainer.style.boxShadow = `0px 5px 8px ${this._themeService.getTheme().getColor(widgetShadow)}`;
|
||||
this._domNode.appendChild(this._treeContainer);
|
||||
|
||||
|
||||
const filterConfig = BreadcrumbsConfig.FilterOnType.bindTo(this._configurationService);
|
||||
this._disposables.push(filterConfig);
|
||||
|
||||
this._layoutInfo = { maxHeight, width, arrowSize, arrowOffset, inputHeight: 0 };
|
||||
this._tree = this._createTree(this._treeContainer);
|
||||
|
||||
this._disposables.push(this._tree.onDidChangeSelection(e => {
|
||||
if (e.browserEvent !== this._fakeEvent) {
|
||||
const target = this._getTargetFromEvent(e.elements[0], e.browserEvent);
|
||||
if (target) {
|
||||
setTimeout(_ => {// need to debounce here because this disposes the tree and the tree doesn't like to be disposed on click
|
||||
this._onDidPickElement.fire({ target, payload: undefined });
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
}, onUnexpectedError);
|
||||
}));
|
||||
this._disposables.push(this._tree.onDidChangeFocus(e => {
|
||||
const target = this._getTargetFromEvent(e.elements[0], e.browserEvent);
|
||||
if (target) {
|
||||
this._onDidFocusElement.fire({ target, payload: undefined });
|
||||
}
|
||||
}));
|
||||
this._disposables.push(this._tree.onDidChangeContentHeight(() => {
|
||||
this._layout();
|
||||
}));
|
||||
|
||||
// filter on type: state
|
||||
const cfgFilterOnType = BreadcrumbsConfig.FilterOnType.bindTo(this._configurationService);
|
||||
this._tree.updateOptions({ filterOnType: cfgFilterOnType.getValue() });
|
||||
this._disposables.push(this._tree.onDidUpdateOptions(e => {
|
||||
this._configurationService.updateValue(cfgFilterOnType.name, e.filterOnType, ConfigurationTarget.MEMORY);
|
||||
}));
|
||||
|
||||
this._domNode.focus();
|
||||
|
||||
this._setInput(input).then(() => {
|
||||
this._layout();
|
||||
}).catch(onUnexpectedError);
|
||||
}
|
||||
|
||||
private _layout(info: ILayoutInfo = this._layoutInfo): void {
|
||||
protected _layout(): void {
|
||||
|
||||
let count = 0;
|
||||
let nav = this._tree.getNavigator(undefined, false);
|
||||
while (nav.next() && count < 13) { count += 1; }
|
||||
|
||||
let headerHeight = 2 * info.arrowSize;
|
||||
let treeHeight = Math.min(info.maxHeight - headerHeight, count * 22);
|
||||
let totalHeight = treeHeight + headerHeight;
|
||||
const headerHeight = 2 * this._layoutInfo.arrowSize;
|
||||
const treeHeight = Math.min(this._layoutInfo.maxHeight - headerHeight, this._tree.contentHeight);
|
||||
const totalHeight = treeHeight + headerHeight;
|
||||
|
||||
this._domNode.style.height = `${totalHeight}px`;
|
||||
this._domNode.style.width = `${info.width}px`;
|
||||
this._arrow.style.top = `-${2 * info.arrowSize}px`;
|
||||
this._arrow.style.borderWidth = `${info.arrowSize}px`;
|
||||
this._arrow.style.marginLeft = `${info.arrowOffset}px`;
|
||||
this._domNode.style.width = `${this._layoutInfo.width}px`;
|
||||
this._arrow.style.top = `-${2 * this._layoutInfo.arrowSize}px`;
|
||||
this._arrow.style.borderWidth = `${this._layoutInfo.arrowSize}px`;
|
||||
this._arrow.style.marginLeft = `${this._layoutInfo.arrowOffset}px`;
|
||||
this._treeContainer.style.height = `${treeHeight}px`;
|
||||
this._treeContainer.style.width = `${info.width}px`;
|
||||
this._tree.layout();
|
||||
this._layoutInfo = info;
|
||||
this._treeContainer.style.width = `${this._layoutInfo.width}px`;
|
||||
this._tree.layout(treeHeight, this._layoutInfo.width);
|
||||
|
||||
}
|
||||
|
||||
protected abstract _getInput(input: BreadcrumbElement): any;
|
||||
protected abstract _getInitialSelection(tree: ITree, input: BreadcrumbElement): any;
|
||||
protected abstract _completeTreeConfiguration(config: IHighlightingTreeConfiguration): IHighlightingTreeConfiguration;
|
||||
protected abstract _getTargetFromEvent(element: any, payload: any): any | undefined;
|
||||
protected abstract _setInput(element: BreadcrumbElement): Promise<void>;
|
||||
protected abstract _createTree(container: HTMLElement): Tree<any, any>;
|
||||
protected abstract _getTargetFromEvent(element: any, payload: UIEvent | undefined): any | undefined;
|
||||
}
|
||||
|
||||
//#region - Files
|
||||
|
||||
export class FileDataSource implements IDataSource {
|
||||
class FileVirtualDelegate implements IListVirtualDelegate<IFileStat | IWorkspaceFolder> {
|
||||
getHeight(_element: IFileStat | IWorkspaceFolder) {
|
||||
return 22;
|
||||
}
|
||||
getTemplateId(_element: IFileStat | IWorkspaceFolder): string {
|
||||
return 'FileStat';
|
||||
}
|
||||
}
|
||||
|
||||
private readonly _parents = new WeakMap<object, IWorkspaceFolder | IFileStat>();
|
||||
|
||||
constructor(
|
||||
@IFileService private readonly _fileService: IFileService,
|
||||
) { }
|
||||
|
||||
getId(tree: ITree, element: IWorkspace | IWorkspaceFolder | IFileStat | URI): string {
|
||||
class FileIdentityProvider implements IIdentityProvider<IWorkspace | IWorkspaceFolder | IFileStat | URI> {
|
||||
getId(element: IWorkspace | IWorkspaceFolder | IFileStat | URI): { toString(): string; } {
|
||||
if (URI.isUri(element)) {
|
||||
return element.toString();
|
||||
} else if (IWorkspace.isIWorkspace(element)) {
|
||||
@@ -222,12 +183,26 @@ export class FileDataSource implements IDataSource {
|
||||
return element.resource.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hasChildren(tree: ITree, element: IWorkspace | IWorkspaceFolder | IFileStat | URI): boolean {
|
||||
return URI.isUri(element) || IWorkspace.isIWorkspace(element) || IWorkspaceFolder.isIWorkspaceFolder(element) || element.isDirectory;
|
||||
|
||||
class FileDataSource implements IAsyncDataSource<IWorkspace | URI, IWorkspaceFolder | IFileStat> {
|
||||
|
||||
private readonly _parents = new WeakMap<object, IWorkspaceFolder | IFileStat>();
|
||||
|
||||
constructor(
|
||||
@IFileService private readonly _fileService: IFileService,
|
||||
) { }
|
||||
|
||||
hasChildren(element: IWorkspace | URI | IWorkspaceFolder | IFileStat): boolean {
|
||||
return URI.isUri(element)
|
||||
|| IWorkspace.isIWorkspace(element)
|
||||
|| IWorkspaceFolder.isIWorkspaceFolder(element)
|
||||
|| element.isDirectory;
|
||||
}
|
||||
|
||||
getChildren(tree: ITree, element: IWorkspace | IWorkspaceFolder | IFileStat | URI): Promise<IWorkspaceFolder[] | IFileStat[]> {
|
||||
getChildren(element: IWorkspace | URI | IWorkspaceFolder | IFileStat): Promise<(IWorkspaceFolder | IFileStat)[]> {
|
||||
|
||||
if (IWorkspace.isIWorkspace(element)) {
|
||||
return Promise.resolve(element.folders).then(folders => {
|
||||
for (let child of folders) {
|
||||
@@ -245,19 +220,62 @@ export class FileDataSource implements IDataSource {
|
||||
uri = element.resource;
|
||||
}
|
||||
return this._fileService.resolveFile(uri).then(stat => {
|
||||
for (let child of stat.children) {
|
||||
for (const child of stat.children || []) {
|
||||
this._parents.set(stat, child);
|
||||
}
|
||||
return stat.children;
|
||||
return stat.children || [];
|
||||
});
|
||||
}
|
||||
|
||||
getParent(tree: ITree, element: IWorkspace | URI | IWorkspaceFolder | IFileStat): Promise<IWorkspaceFolder | IFileStat> {
|
||||
return Promise.resolve(this._parents.get(element));
|
||||
}
|
||||
}
|
||||
|
||||
export class FileFilter implements IFilter {
|
||||
class FileRenderer implements ITreeRenderer<IFileStat | IWorkspaceFolder, FuzzyScore, IResourceLabel> {
|
||||
|
||||
readonly templateId: string = 'FileStat';
|
||||
|
||||
constructor(
|
||||
private readonly _labels: ResourceLabels,
|
||||
@IConfigurationService private readonly _configService: IConfigurationService,
|
||||
) { }
|
||||
|
||||
|
||||
renderTemplate(container: HTMLElement): IResourceLabel {
|
||||
return this._labels.create(container, { supportHighlights: true });
|
||||
}
|
||||
|
||||
renderElement(node: ITreeNode<IWorkspaceFolder | IFileStat, [number, number, number]>, index: number, templateData: IResourceLabel): void {
|
||||
const fileDecorations = this._configService.getValue<{ colors: boolean, badges: boolean }>('explorer.decorations');
|
||||
const { element } = node;
|
||||
let resource: URI;
|
||||
let fileKind: FileKind;
|
||||
if (IWorkspaceFolder.isIWorkspaceFolder(element)) {
|
||||
resource = element.uri;
|
||||
fileKind = FileKind.ROOT_FOLDER;
|
||||
} else {
|
||||
resource = element.resource;
|
||||
fileKind = element.isDirectory ? FileKind.FOLDER : FileKind.FILE;
|
||||
}
|
||||
templateData.setFile(resource, {
|
||||
fileKind,
|
||||
hidePath: true,
|
||||
fileDecorations: fileDecorations,
|
||||
matches: createMatches(node.filterData),
|
||||
extraClasses: ['picker-item']
|
||||
});
|
||||
}
|
||||
|
||||
disposeTemplate(templateData: IResourceLabel): void {
|
||||
templateData.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
class FileNavigationLabelProvider implements IKeyboardNavigationLabelProvider<IWorkspaceFolder | IFileStat> {
|
||||
|
||||
getKeyboardNavigationLabel(element: IWorkspaceFolder | IFileStat): { toString(): string; } {
|
||||
return element.name;
|
||||
}
|
||||
}
|
||||
|
||||
class FileFilter implements ITreeFilter<IWorkspaceFolder | IFileStat> {
|
||||
|
||||
private readonly _cachedExpressions = new Map<string, glob.ParsedExpression>();
|
||||
private readonly _disposables: IDisposable[] = [];
|
||||
@@ -281,7 +299,7 @@ export class FileFilter implements IFilter {
|
||||
continue;
|
||||
}
|
||||
let patternAbs = pattern.indexOf('**/') !== 0
|
||||
? join(folder.uri.path, pattern)
|
||||
? posix.join(folder.uri.path, pattern)
|
||||
: pattern;
|
||||
|
||||
adjustedConfig[patternAbs] = excludesConfig[pattern];
|
||||
@@ -301,7 +319,7 @@ export class FileFilter implements IFilter {
|
||||
dispose(this._disposables);
|
||||
}
|
||||
|
||||
isVisible(tree: ITree, element: IWorkspaceFolder | IFileStat): boolean {
|
||||
filter(element: IWorkspaceFolder | IFileStat, _parentVisibility: TreeVisibility): boolean {
|
||||
if (IWorkspaceFolder.isIWorkspaceFolder(element)) {
|
||||
// not a file
|
||||
return true;
|
||||
@@ -312,77 +330,24 @@ export class FileFilter implements IFilter {
|
||||
return true;
|
||||
}
|
||||
|
||||
const expression = this._cachedExpressions.get(folder.uri.toString());
|
||||
const expression = this._cachedExpressions.get(folder.uri.toString())!;
|
||||
return !expression(element.resource.path, basename(element.resource));
|
||||
}
|
||||
}
|
||||
|
||||
export class FileHighlighter implements IHighlighter {
|
||||
getHighlightsStorageKey(element: IFileStat | IWorkspaceFolder): string {
|
||||
return IWorkspaceFolder.isIWorkspaceFolder(element) ? element.uri.toString() : element.resource.toString();
|
||||
}
|
||||
getHighlights(tree: ITree, element: IFileStat | IWorkspaceFolder, pattern: string): FuzzyScore {
|
||||
return fuzzyScore(pattern, pattern.toLowerCase(), 0, element.name, element.name.toLowerCase(), 0, true);
|
||||
}
|
||||
}
|
||||
|
||||
export class FileRenderer implements IRenderer {
|
||||
|
||||
constructor(
|
||||
private readonly _labels: ResourceLabels,
|
||||
@IConfigurationService private readonly _configService: IConfigurationService,
|
||||
) { }
|
||||
|
||||
getHeight(tree: ITree, element: any): number {
|
||||
return 22;
|
||||
}
|
||||
|
||||
getTemplateId(tree: ITree, element: any): string {
|
||||
return 'FileStat';
|
||||
}
|
||||
|
||||
renderTemplate(tree: ITree, templateId: string, container: HTMLElement) {
|
||||
return this._labels.create(container, { supportHighlights: true });
|
||||
}
|
||||
|
||||
renderElement(tree: ITree, element: IFileStat | IWorkspaceFolder, templateId: string, templateData: IResourceLabel): void {
|
||||
let fileDecorations = this._configService.getValue<{ colors: boolean, badges: boolean }>('explorer.decorations');
|
||||
let resource: URI;
|
||||
let fileKind: FileKind;
|
||||
if (IWorkspaceFolder.isIWorkspaceFolder(element)) {
|
||||
resource = element.uri;
|
||||
fileKind = FileKind.ROOT_FOLDER;
|
||||
} else {
|
||||
resource = element.resource;
|
||||
fileKind = element.isDirectory ? FileKind.FOLDER : FileKind.FILE;
|
||||
}
|
||||
templateData.setFile(resource, {
|
||||
fileKind,
|
||||
hidePath: true,
|
||||
fileDecorations: fileDecorations,
|
||||
matches: createMatches((tree as HighlightingWorkbenchTree).getHighlighterScore(element)),
|
||||
extraClasses: ['picker-item']
|
||||
});
|
||||
}
|
||||
|
||||
disposeTemplate(tree: ITree, templateId: string, templateData: IResourceLabel): void {
|
||||
templateData.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
export class FileSorter implements ISorter {
|
||||
compare(tree: ITree, a: IFileStat | IWorkspaceFolder, b: IFileStat | IWorkspaceFolder): number {
|
||||
export class FileSorter implements ITreeSorter<IFileStat | IWorkspaceFolder> {
|
||||
compare(a: IFileStat | IWorkspaceFolder, b: IFileStat | IWorkspaceFolder): number {
|
||||
if (IWorkspaceFolder.isIWorkspaceFolder(a) && IWorkspaceFolder.isIWorkspaceFolder(b)) {
|
||||
return a.index - b.index;
|
||||
}
|
||||
if ((a as IFileStat).isDirectory === (b as IFileStat).isDirectory) {
|
||||
// same type -> compare on names
|
||||
return compareFileNames(a.name, b.name);
|
||||
} else if ((a as IFileStat).isDirectory) {
|
||||
return -1;
|
||||
} else {
|
||||
if ((a as IFileStat).isDirectory === (b as IFileStat).isDirectory) {
|
||||
// same type -> compare on names
|
||||
return compareFileNames(a.name, b.name);
|
||||
} else if ((a as IFileStat).isDirectory) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -399,44 +364,69 @@ export class BreadcrumbsFilePicker extends BreadcrumbsPicker {
|
||||
super(parent, instantiationService, themeService, configService);
|
||||
}
|
||||
|
||||
protected _getInput(input: BreadcrumbElement): any {
|
||||
let { uri, kind } = (input as FileElement);
|
||||
if (kind === FileKind.ROOT_FOLDER) {
|
||||
return this._workspaceService.getWorkspace();
|
||||
} else {
|
||||
return dirname(uri);
|
||||
}
|
||||
}
|
||||
_createTree(container: HTMLElement) {
|
||||
|
||||
protected _getInitialSelection(tree: ITree, input: BreadcrumbElement): any {
|
||||
let { uri } = (input as FileElement);
|
||||
let nav = tree.getNavigator();
|
||||
while (nav.next()) {
|
||||
let cur = nav.current();
|
||||
let candidate = IWorkspaceFolder.isIWorkspaceFolder(cur) ? cur.uri : (cur as IFileStat).resource;
|
||||
if (isEqual(uri, candidate)) {
|
||||
return cur;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
// tree icon theme specials
|
||||
dom.addClass(this._treeContainer, 'file-icon-themable-tree');
|
||||
dom.addClass(this._treeContainer, 'show-file-icons');
|
||||
const onFileIconThemeChange = (fileIconTheme: IFileIconTheme) => {
|
||||
dom.toggleClass(this._treeContainer, 'align-icons-and-twisties', fileIconTheme.hasFileIcons && !fileIconTheme.hasFolderIcons);
|
||||
dom.toggleClass(this._treeContainer, 'hide-arrows', fileIconTheme.hidesExplorerArrows === true);
|
||||
};
|
||||
this._disposables.push(this._themeService.onDidFileIconThemeChange(onFileIconThemeChange));
|
||||
onFileIconThemeChange(this._themeService.getFileIconTheme());
|
||||
|
||||
protected _completeTreeConfiguration(config: IHighlightingTreeConfiguration): IHighlightingTreeConfiguration {
|
||||
// todo@joh reuse explorer implementations?
|
||||
const filter = this._instantiationService.createInstance(FileFilter);
|
||||
this._disposables.push(filter);
|
||||
|
||||
config.dataSource = this._instantiationService.createInstance(FileDataSource);
|
||||
const labels = this._instantiationService.createInstance(ResourceLabels, DEFAULT_LABELS_CONTAINER /* TODO@Jo visibility propagation */);
|
||||
this._disposables.push(labels);
|
||||
config.renderer = this._instantiationService.createInstance(FileRenderer, labels);
|
||||
config.sorter = new FileSorter();
|
||||
config.highlighter = new FileHighlighter();
|
||||
config.filter = filter;
|
||||
return config;
|
||||
|
||||
return this._instantiationService.createInstance(
|
||||
WorkbenchAsyncDataTree,
|
||||
container,
|
||||
new FileVirtualDelegate(),
|
||||
[this._instantiationService.createInstance(FileRenderer, labels)],
|
||||
this._instantiationService.createInstance(FileDataSource),
|
||||
{
|
||||
filterOnType: true,
|
||||
multipleSelectionSupport: false,
|
||||
sorter: new FileSorter(),
|
||||
filter: this._instantiationService.createInstance(FileFilter),
|
||||
identityProvider: new FileIdentityProvider(),
|
||||
keyboardNavigationLabelProvider: new FileNavigationLabelProvider()
|
||||
}
|
||||
) as WorkbenchAsyncDataTree<BreadcrumbElement, any, FuzzyScore>;
|
||||
}
|
||||
|
||||
_setInput(element: BreadcrumbElement): Promise<void> {
|
||||
const { uri, kind } = (element as FileElement);
|
||||
let input: IWorkspace | URI;
|
||||
if (kind === FileKind.ROOT_FOLDER) {
|
||||
input = this._workspaceService.getWorkspace();
|
||||
} else {
|
||||
input = dirname(uri);
|
||||
}
|
||||
|
||||
const tree = this._tree as WorkbenchAsyncDataTree<IWorkspace | URI, IWorkspaceFolder | IFileStat, FuzzyScore>;
|
||||
return tree.setInput(input).then(() => {
|
||||
let focusElement: IWorkspaceFolder | IFileStat | undefined;
|
||||
for (const { element } of tree.getNode().children) {
|
||||
if (IWorkspaceFolder.isIWorkspaceFolder(element) && isEqual(element.uri, uri)) {
|
||||
focusElement = element;
|
||||
break;
|
||||
} else if (isEqual((element as IFileStat).resource, uri)) {
|
||||
focusElement = element as IFileStat;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (focusElement) {
|
||||
tree.reveal(focusElement, 0.5);
|
||||
tree.setFocus([focusElement], this._fakeEvent);
|
||||
}
|
||||
tree.domFocus();
|
||||
});
|
||||
}
|
||||
|
||||
protected _getTargetFromEvent(element: any, _payload: any): any | undefined {
|
||||
// todo@joh
|
||||
if (element && !IWorkspaceFolder.isIWorkspaceFolder(element) && !(element as IFileStat).isDirectory) {
|
||||
return new FileElement((element as IFileStat).resource, FileKind.FILE);
|
||||
}
|
||||
@@ -446,52 +436,84 @@ export class BreadcrumbsFilePicker extends BreadcrumbsPicker {
|
||||
|
||||
//#region - Symbols
|
||||
|
||||
class OutlineHighlighter implements IHighlighter {
|
||||
getHighlights(tree: ITree, element: OutlineElement, pattern: string): FuzzyScore {
|
||||
OutlineModel.get(element).updateMatches(pattern);
|
||||
return element.score;
|
||||
}
|
||||
}
|
||||
|
||||
export class BreadcrumbsOutlinePicker extends BreadcrumbsPicker {
|
||||
|
||||
protected _getInput(input: BreadcrumbElement): any {
|
||||
let element = input as TreeElement;
|
||||
let model = OutlineModel.get(element);
|
||||
model.updateMatches('');
|
||||
return model;
|
||||
protected readonly _symbolSortOrder: BreadcrumbsConfig<'position' | 'name' | 'type'>;
|
||||
|
||||
constructor(
|
||||
parent: HTMLElement,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IWorkbenchThemeService themeService: IWorkbenchThemeService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
) {
|
||||
super(parent, instantiationService, themeService, configurationService);
|
||||
this._symbolSortOrder = BreadcrumbsConfig.SymbolSortOrder.bindTo(this._configurationService);
|
||||
}
|
||||
|
||||
protected _getInitialSelection(_tree: ITree, input: BreadcrumbElement): any {
|
||||
return input instanceof OutlineModel ? undefined : input;
|
||||
protected _createTree(container: HTMLElement) {
|
||||
return this._instantiationService.createInstance<
|
||||
HTMLElement,
|
||||
IListVirtualDelegate<OutlineItem>,
|
||||
ITreeRenderer<any, FuzzyScore, any>[],
|
||||
IDataSource<OutlineModel, OutlineItem>,
|
||||
IDataTreeOptions<OutlineItem, FuzzyScore>,
|
||||
WorkbenchDataTree<OutlineModel, OutlineItem, FuzzyScore>
|
||||
>(
|
||||
WorkbenchDataTree,
|
||||
container,
|
||||
new OutlineVirtualDelegate(),
|
||||
[new OutlineGroupRenderer(), this._instantiationService.createInstance(OutlineElementRenderer)],
|
||||
new OutlineDataSource(),
|
||||
{
|
||||
filterOnType: true,
|
||||
expandOnlyOnTwistieClick: true,
|
||||
multipleSelectionSupport: false,
|
||||
sorter: new OutlineItemComparator(this._getOutlineItemCompareType()),
|
||||
identityProvider: new OutlineIdentityProvider(),
|
||||
keyboardNavigationLabelProvider: this._instantiationService.createInstance(OutlineNavigationLabelProvider)
|
||||
}
|
||||
) as WorkbenchDataTree<OutlineModel, OutlineItem, FuzzyScore>;
|
||||
}
|
||||
|
||||
protected _completeTreeConfiguration(config: IHighlightingTreeConfiguration): IHighlightingTreeConfiguration {
|
||||
config.dataSource = this._instantiationService.createInstance(OutlineDataSource);
|
||||
config.renderer = this._instantiationService.createInstance(OutlineRenderer);
|
||||
config.sorter = new OutlineItemComparator(this._getOutlineItemComparator());
|
||||
config.highlighter = new OutlineHighlighter();
|
||||
return config;
|
||||
dispose(): void {
|
||||
this._symbolSortOrder.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
protected _getTargetFromEvent(element: any, payload: any): any | undefined {
|
||||
if (payload && payload.didClickOnTwistie) {
|
||||
return;
|
||||
protected _setInput(input: BreadcrumbElement): Promise<void> {
|
||||
const element = input as TreeElement;
|
||||
const model = OutlineModel.get(element)!;
|
||||
const tree = this._tree as WorkbenchDataTree<OutlineModel, any, FuzzyScore>;
|
||||
tree.setInput(model);
|
||||
|
||||
let focusElement: TreeElement;
|
||||
if (element === model) {
|
||||
focusElement = tree.navigate().first();
|
||||
} else {
|
||||
focusElement = element;
|
||||
}
|
||||
tree.reveal(focusElement, 0.5);
|
||||
tree.setFocus([focusElement], this._fakeEvent);
|
||||
tree.domFocus();
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
protected _getTargetFromEvent(element: any): any | undefined {
|
||||
if (element instanceof OutlineElement) {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
|
||||
private _getOutlineItemComparator(): OutlineItemCompareType {
|
||||
private _getOutlineItemCompareType(): OutlineSortOrder {
|
||||
switch (this._symbolSortOrder.getValue()) {
|
||||
case 'name':
|
||||
return OutlineItemCompareType.ByName;
|
||||
return OutlineSortOrder.ByName;
|
||||
case 'type':
|
||||
return OutlineItemCompareType.ByKind;
|
||||
return OutlineSortOrder.ByKind;
|
||||
case 'position':
|
||||
default:
|
||||
return OutlineItemCompareType.ByPosition;
|
||||
return OutlineSortOrder.ByPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
|
||||
interface ISerializedUntitledEditorInput {
|
||||
resource: string;
|
||||
resourceJSON: object;
|
||||
modeId: string;
|
||||
modeId: string | null;
|
||||
encoding: string;
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ class UntitledEditorInputFactory implements IEditorInputFactory {
|
||||
@ITextFileService private readonly textFileService: ITextFileService
|
||||
) { }
|
||||
|
||||
serialize(editorInput: EditorInput): string {
|
||||
serialize(editorInput: EditorInput): string | null {
|
||||
if (!this.textFileService.isHotExitEnabled) {
|
||||
return null; // never restore untitled unless hot exit is enabled
|
||||
}
|
||||
@@ -170,7 +170,7 @@ interface ISerializedSideBySideEditorInput {
|
||||
// Register Side by Side Editor Input Factory
|
||||
class SideBySideEditorInputFactory implements IEditorInputFactory {
|
||||
|
||||
serialize(editorInput: EditorInput): string {
|
||||
serialize(editorInput: EditorInput): string | null {
|
||||
const input = <SideBySideEditorInput>editorInput;
|
||||
|
||||
if (input.details && input.master) {
|
||||
@@ -198,7 +198,7 @@ class SideBySideEditorInputFactory implements IEditorInputFactory {
|
||||
return null;
|
||||
}
|
||||
|
||||
deserialize(instantiationService: IInstantiationService, serializedEditorInput: string): EditorInput {
|
||||
deserialize(instantiationService: IInstantiationService, serializedEditorInput: string): EditorInput | null {
|
||||
const deserialized: ISerializedSideBySideEditorInput = JSON.parse(serializedEditorInput);
|
||||
|
||||
const registry = Registry.as<IEditorInputFactoryRegistry>(EditorInputExtensions.EditorInputFactories);
|
||||
@@ -266,7 +266,7 @@ export class QuickOpenActionContributor extends ActionBarContributor {
|
||||
return actions;
|
||||
}
|
||||
|
||||
private getEntry(context: any): IEditorQuickOpenEntry {
|
||||
private getEntry(context: any): IEditorQuickOpenEntry | null {
|
||||
if (!context || !context.element) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { GroupIdentifier, IWorkbenchEditorConfiguration, IWorkbenchEditorPartConfiguration, EditorOptions, TextEditorOptions, IEditorInput, IEditorIdentifier, IEditorCloseEvent, IEditor } from 'vs/workbench/common/editor';
|
||||
import { GroupIdentifier, IWorkbenchEditorConfiguration, EditorOptions, TextEditorOptions, IEditorInput, IEditorIdentifier, IEditorCloseEvent, IEditor, IEditorPartOptions } from 'vs/workbench/common/editor';
|
||||
import { EditorGroup } from 'vs/workbench/common/editor/editorGroup';
|
||||
import { IEditorGroup, GroupDirection, IAddGroupOptions, IMergeGroupOptions, GroupsOrder, IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
|
||||
import { IEditorGroup, GroupDirection, IAddGroupOptions, IMergeGroupOptions, GroupsOrder } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Dimension } from 'vs/base/browser/dom';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
@@ -18,13 +18,13 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
|
||||
|
||||
export const EDITOR_TITLE_HEIGHT = 35;
|
||||
|
||||
export interface IEditorPartCreationOptions {
|
||||
restorePreviousState: boolean;
|
||||
}
|
||||
|
||||
export const DEFAULT_EDITOR_MIN_DIMENSIONS = new Dimension(220, 70);
|
||||
export const DEFAULT_EDITOR_MAX_DIMENSIONS = new Dimension(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY);
|
||||
|
||||
export interface IEditorPartOptions extends IWorkbenchEditorPartConfiguration {
|
||||
iconTheme?: string;
|
||||
}
|
||||
|
||||
export const DEFAULT_EDITOR_PART_OPTIONS: IEditorPartOptions = {
|
||||
showTabs: true,
|
||||
highlightModifiedTabs: false,
|
||||
@@ -77,7 +77,7 @@ export interface IEditorOpeningEvent extends IEditorIdentifier {
|
||||
* to return a promise that resolves to NULL to prevent the opening
|
||||
* alltogether.
|
||||
*/
|
||||
prevent(callback: () => Promise<IEditor>): void;
|
||||
prevent(callback: () => undefined | Promise<IEditor | undefined>): void;
|
||||
}
|
||||
|
||||
export interface IEditorGroupsAccessor {
|
||||
@@ -87,7 +87,7 @@ export interface IEditorGroupsAccessor {
|
||||
readonly partOptions: IEditorPartOptions;
|
||||
readonly onDidEditorPartOptionsChange: Event<IEditorPartOptionsChangeEvent>;
|
||||
|
||||
getGroup(identifier: GroupIdentifier): IEditorGroupView;
|
||||
getGroup(identifier: GroupIdentifier): IEditorGroupView | undefined;
|
||||
getGroups(order: GroupsOrder): IEditorGroupView[];
|
||||
|
||||
activateGroup(identifier: IEditorGroupView | GroupIdentifier): IEditorGroupView;
|
||||
@@ -146,15 +146,3 @@ export interface EditorServiceImpl extends IEditorService {
|
||||
*/
|
||||
readonly onDidOpenEditorFail: Event<IEditorIdentifier>;
|
||||
}
|
||||
|
||||
/**
|
||||
* A sub-interface of IEditorGroupsService to hide some workbench-core specific
|
||||
* methods from clients.
|
||||
*/
|
||||
export interface EditorGroupsServiceImpl extends IEditorGroupsService {
|
||||
|
||||
/**
|
||||
* A promise that resolves when groups have been restored.
|
||||
*/
|
||||
readonly whenRestored: Promise<void>;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { IEditorInput, EditorInput, IEditorIdentifier, ConfirmResult, IEditorCom
|
||||
import { QuickOpenEntryGroup } from 'vs/base/parts/quickopen/browser/quickOpenModel';
|
||||
import { EditorQuickOpenEntry, EditorQuickOpenEntryGroup, IEditorQuickOpenEntry, QuickOpenAction } from 'vs/workbench/browser/quickopen';
|
||||
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
|
||||
import { IPartService } from 'vs/workbench/services/part/common/partService';
|
||||
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { IResourceInput } from 'vs/platform/editor/common/editor';
|
||||
import { IHistoryService } from 'vs/workbench/services/history/common/history';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
@@ -18,7 +18,7 @@ import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { IWindowsService } from 'vs/platform/windows/common/windows';
|
||||
import { CLOSE_EDITOR_COMMAND_ID, NAVIGATE_ALL_EDITORS_GROUP_PREFIX, MOVE_ACTIVE_EDITOR_COMMAND_ID, NAVIGATE_IN_ACTIVE_GROUP_PREFIX, ActiveEditorMoveArguments, SPLIT_EDITOR_LEFT, SPLIT_EDITOR_RIGHT, SPLIT_EDITOR_UP, SPLIT_EDITOR_DOWN, splitEditor, LAYOUT_EDITOR_GROUPS_COMMAND_ID, mergeAllGroups } from 'vs/workbench/browser/parts/editor/editorCommands';
|
||||
import { IEditorGroupsService, IEditorGroup, GroupsArrangement, EditorsOrder, GroupLocation, GroupDirection, preferredSideBySideGroupDirection, IFindGroupScope, GroupOrientation, EditorGroupLayout, GroupsOrder } from 'vs/workbench/services/group/common/editorGroupsService';
|
||||
import { IEditorGroupsService, IEditorGroup, GroupsArrangement, EditorsOrder, GroupLocation, GroupDirection, preferredSideBySideGroupDirection, IFindGroupScope, GroupOrientation, EditorGroupLayout, GroupsOrder } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
@@ -188,20 +188,22 @@ export class JoinTwoGroupsAction extends Action {
|
||||
}
|
||||
|
||||
run(context?: IEditorIdentifier): Promise<any> {
|
||||
let sourceGroup: IEditorGroup;
|
||||
let sourceGroup: IEditorGroup | undefined;
|
||||
if (context && typeof context.groupId === 'number') {
|
||||
sourceGroup = this.editorGroupService.getGroup(context.groupId);
|
||||
} else {
|
||||
sourceGroup = this.editorGroupService.activeGroup;
|
||||
}
|
||||
|
||||
const targetGroupDirections = [GroupDirection.RIGHT, GroupDirection.DOWN, GroupDirection.LEFT, GroupDirection.UP];
|
||||
for (const targetGroupDirection of targetGroupDirections) {
|
||||
const targetGroup = this.editorGroupService.findGroup({ direction: targetGroupDirection }, sourceGroup);
|
||||
if (targetGroup && sourceGroup !== targetGroup) {
|
||||
this.editorGroupService.mergeGroup(sourceGroup, targetGroup);
|
||||
if (sourceGroup) {
|
||||
const targetGroupDirections = [GroupDirection.RIGHT, GroupDirection.DOWN, GroupDirection.LEFT, GroupDirection.UP];
|
||||
for (const targetGroupDirection of targetGroupDirections) {
|
||||
const targetGroup = this.editorGroupService.findGroup({ direction: targetGroupDirection }, sourceGroup);
|
||||
if (targetGroup && sourceGroup !== targetGroup) {
|
||||
this.editorGroupService.mergeGroup(sourceGroup, targetGroup);
|
||||
|
||||
return Promise.resolve(true);
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -428,7 +430,7 @@ export class OpenToSideFromQuickOpenAction extends Action {
|
||||
if (entry) {
|
||||
const input = entry.getInput();
|
||||
if (input instanceof EditorInput) {
|
||||
return this.editorService.openEditor(input, entry.getOptions(), SIDE_GROUP);
|
||||
return this.editorService.openEditor(input, entry.getOptions() || undefined, SIDE_GROUP);
|
||||
}
|
||||
|
||||
const resourceInput = input as IResourceInput;
|
||||
@@ -441,7 +443,7 @@ export class OpenToSideFromQuickOpenAction extends Action {
|
||||
}
|
||||
}
|
||||
|
||||
export function toEditorQuickOpenEntry(element: any): IEditorQuickOpenEntry {
|
||||
export function toEditorQuickOpenEntry(element: any): IEditorQuickOpenEntry | null {
|
||||
|
||||
// QuickOpenEntryGroup
|
||||
if (element instanceof QuickOpenEntryGroup) {
|
||||
@@ -491,13 +493,13 @@ export class CloseOneEditorAction extends Action {
|
||||
}
|
||||
|
||||
run(context?: IEditorCommandsContext): Promise<any> {
|
||||
let group: IEditorGroup;
|
||||
let editorIndex: number;
|
||||
let group: IEditorGroup | undefined;
|
||||
let editorIndex: number | undefined;
|
||||
if (context) {
|
||||
group = this.editorGroupService.getGroup(context.groupId);
|
||||
|
||||
if (group) {
|
||||
editorIndex = context.editorIndex; // only allow editor at index if group is valid
|
||||
editorIndex = context.editorIndex!; // only allow editor at index if group is valid
|
||||
}
|
||||
}
|
||||
|
||||
@@ -579,7 +581,7 @@ export class CloseLeftEditorsInGroupAction extends Action {
|
||||
}
|
||||
}
|
||||
|
||||
function getTarget(editorService: IEditorService, editorGroupService: IEditorGroupsService, context?: IEditorIdentifier): { editor: IEditorInput, group: IEditorGroup } {
|
||||
function getTarget(editorService: IEditorService, editorGroupService: IEditorGroupsService, context?: IEditorIdentifier): { editor: IEditorInput | null, group: IEditorGroup | undefined } {
|
||||
if (context) {
|
||||
return { editor: context.editor, group: editorGroupService.getGroup(context.groupId) };
|
||||
}
|
||||
@@ -593,7 +595,7 @@ export abstract class BaseCloseAllAction extends Action {
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
clazz: string,
|
||||
clazz: string | undefined,
|
||||
private textFileService: ITextFileService,
|
||||
protected editorGroupService: IEditorGroupsService
|
||||
) {
|
||||
@@ -629,9 +631,9 @@ export abstract class BaseCloseAllAction extends Action {
|
||||
|
||||
let saveOrRevertPromise: Promise<boolean>;
|
||||
if (confirm === ConfirmResult.DONT_SAVE) {
|
||||
saveOrRevertPromise = this.textFileService.revertAll(null, { soft: true }).then(() => true);
|
||||
saveOrRevertPromise = this.textFileService.revertAll(undefined, { soft: true }).then(() => true);
|
||||
} else {
|
||||
saveOrRevertPromise = this.textFileService.saveAll(true).then(res => res.results.every(r => r.success));
|
||||
saveOrRevertPromise = this.textFileService.saveAll(true).then(res => res.results.every(r => !!r.success));
|
||||
}
|
||||
|
||||
return saveOrRevertPromise.then(success => {
|
||||
@@ -703,8 +705,8 @@ export class CloseEditorsInOtherGroupsAction extends Action {
|
||||
run(context?: IEditorIdentifier): Promise<any> {
|
||||
const groupToSkip = context ? this.editorGroupService.getGroup(context.groupId) : this.editorGroupService.activeGroup;
|
||||
return Promise.all(this.editorGroupService.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE).map(g => {
|
||||
if (g.id === groupToSkip.id) {
|
||||
return Promise.resolve(null);
|
||||
if (groupToSkip && g.id === groupToSkip.id) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return g.closeAllEditors();
|
||||
@@ -732,7 +734,7 @@ export class CloseEditorInAllGroupsAction extends Action {
|
||||
return Promise.all(this.editorGroupService.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE).map(g => g.closeEditor(activeEditor)));
|
||||
}
|
||||
|
||||
return Promise.resolve(null);
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -748,22 +750,24 @@ export class BaseMoveGroupAction extends Action {
|
||||
}
|
||||
|
||||
run(context?: IEditorIdentifier): Promise<any> {
|
||||
let sourceGroup: IEditorGroup;
|
||||
let sourceGroup: IEditorGroup | undefined;
|
||||
if (context && typeof context.groupId === 'number') {
|
||||
sourceGroup = this.editorGroupService.getGroup(context.groupId);
|
||||
} else {
|
||||
sourceGroup = this.editorGroupService.activeGroup;
|
||||
}
|
||||
|
||||
const targetGroup = this.findTargetGroup(sourceGroup);
|
||||
if (targetGroup) {
|
||||
this.editorGroupService.moveGroup(sourceGroup, targetGroup, this.direction);
|
||||
if (sourceGroup) {
|
||||
const targetGroup = this.findTargetGroup(sourceGroup);
|
||||
if (targetGroup) {
|
||||
this.editorGroupService.moveGroup(sourceGroup, targetGroup, this.direction);
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
private findTargetGroup(sourceGroup: IEditorGroup): IEditorGroup {
|
||||
private findTargetGroup(sourceGroup: IEditorGroup): IEditorGroup | undefined {
|
||||
const targetNeighbours: GroupDirection[] = [this.direction];
|
||||
|
||||
// Allow the target group to be in alternative locations to support more
|
||||
@@ -882,14 +886,14 @@ export class ResetGroupSizesAction extends Action {
|
||||
export class MaximizeGroupAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.maximizeEditor';
|
||||
static readonly LABEL = nls.localize('maximizeEditor', "Maximize Editor Group and Hide Sidebar");
|
||||
static readonly LABEL = nls.localize('maximizeEditor', "Maximize Editor Group and Hide Side Bar");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IEditorService private readonly editorService: IEditorService,
|
||||
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
|
||||
@IPartService private readonly partService: IPartService
|
||||
@IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
@@ -897,7 +901,7 @@ export class MaximizeGroupAction extends Action {
|
||||
run(): Promise<any> {
|
||||
if (this.editorService.activeEditor) {
|
||||
this.editorGroupService.arrangeGroups(GroupsArrangement.MINIMIZE_OTHERS);
|
||||
this.partService.setSideBarHidden(true);
|
||||
this.layoutService.setSideBarHidden(true);
|
||||
}
|
||||
|
||||
return Promise.resolve(false);
|
||||
@@ -927,10 +931,14 @@ export abstract class BaseNavigateEditorAction extends Action {
|
||||
}
|
||||
|
||||
const group = this.editorGroupService.getGroup(groupId);
|
||||
return group.openEditor(editor);
|
||||
if (group) {
|
||||
return group.openEditor(editor);
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
protected abstract navigate(): IEditorIdentifier;
|
||||
protected abstract navigate(): IEditorIdentifier | undefined;
|
||||
}
|
||||
|
||||
export class OpenNextEditor extends BaseNavigateEditorAction {
|
||||
@@ -947,12 +955,12 @@ export class OpenNextEditor extends BaseNavigateEditorAction {
|
||||
super(id, label, editorGroupService, editorService);
|
||||
}
|
||||
|
||||
protected navigate(): IEditorIdentifier {
|
||||
protected navigate(): IEditorIdentifier | undefined {
|
||||
|
||||
// Navigate in active group if possible
|
||||
const activeGroup = this.editorGroupService.activeGroup;
|
||||
const activeGroupEditors = activeGroup.getEditors(EditorsOrder.SEQUENTIAL);
|
||||
const activeEditorIndex = activeGroupEditors.indexOf(activeGroup.activeEditor);
|
||||
const activeEditorIndex = activeGroup.activeEditor ? activeGroupEditors.indexOf(activeGroup.activeEditor) : -1;
|
||||
if (activeEditorIndex + 1 < activeGroupEditors.length) {
|
||||
return { editor: activeGroupEditors[activeEditorIndex + 1], groupId: activeGroup.id };
|
||||
}
|
||||
@@ -982,12 +990,12 @@ export class OpenPreviousEditor extends BaseNavigateEditorAction {
|
||||
super(id, label, editorGroupService, editorService);
|
||||
}
|
||||
|
||||
protected navigate(): IEditorIdentifier {
|
||||
protected navigate(): IEditorIdentifier | undefined {
|
||||
|
||||
// Navigate in active group if possible
|
||||
const activeGroup = this.editorGroupService.activeGroup;
|
||||
const activeGroupEditors = activeGroup.getEditors(EditorsOrder.SEQUENTIAL);
|
||||
const activeEditorIndex = activeGroupEditors.indexOf(activeGroup.activeEditor);
|
||||
const activeEditorIndex = activeGroup.activeEditor ? activeGroupEditors.indexOf(activeGroup.activeEditor) : -1;
|
||||
if (activeEditorIndex > 0) {
|
||||
return { editor: activeGroupEditors[activeEditorIndex - 1], groupId: activeGroup.id };
|
||||
}
|
||||
@@ -1020,7 +1028,7 @@ export class OpenNextEditorInGroup extends BaseNavigateEditorAction {
|
||||
protected navigate(): IEditorIdentifier {
|
||||
const group = this.editorGroupService.activeGroup;
|
||||
const editors = group.getEditors(EditorsOrder.SEQUENTIAL);
|
||||
const index = editors.indexOf(group.activeEditor);
|
||||
const index = group.activeEditor ? editors.indexOf(group.activeEditor) : -1;
|
||||
|
||||
return { editor: index + 1 < editors.length ? editors[index + 1] : editors[0], groupId: group.id };
|
||||
}
|
||||
@@ -1043,7 +1051,7 @@ export class OpenPreviousEditorInGroup extends BaseNavigateEditorAction {
|
||||
protected navigate(): IEditorIdentifier {
|
||||
const group = this.editorGroupService.activeGroup;
|
||||
const editors = group.getEditors(EditorsOrder.SEQUENTIAL);
|
||||
const index = editors.indexOf(group.activeEditor);
|
||||
const index = group.activeEditor ? editors.indexOf(group.activeEditor) : -1;
|
||||
|
||||
return { editor: index > 0 ? editors[index - 1] : editors[editors.length - 1], groupId: group.id };
|
||||
}
|
||||
@@ -1105,7 +1113,7 @@ export class NavigateForwardAction extends Action {
|
||||
run(): Promise<any> {
|
||||
this.historyService.forward();
|
||||
|
||||
return Promise.resolve(null);
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1121,7 +1129,7 @@ export class NavigateBackwardsAction extends Action {
|
||||
run(): Promise<any> {
|
||||
this.historyService.back();
|
||||
|
||||
return Promise.resolve(null);
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1137,7 +1145,7 @@ export class NavigateToLastEditLocationAction extends Action {
|
||||
run(): Promise<any> {
|
||||
this.historyService.openLastEditLocation();
|
||||
|
||||
return Promise.resolve(null);
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1153,7 +1161,7 @@ export class NavigateLastAction extends Action {
|
||||
run(): Promise<any> {
|
||||
this.historyService.last();
|
||||
|
||||
return Promise.resolve(null);
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1296,7 +1304,7 @@ export class OpenPreviousEditorFromHistoryAction extends Action {
|
||||
run(): Promise<any> {
|
||||
const keys = this.keybindingService.lookupKeybindings(this.id);
|
||||
|
||||
this.quickOpenService.show(null, { quickNavigateConfiguration: { keybindings: keys } });
|
||||
this.quickOpenService.show(undefined, { quickNavigateConfiguration: { keybindings: keys } });
|
||||
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
@@ -1314,7 +1322,7 @@ export class OpenNextRecentlyUsedEditorAction extends Action {
|
||||
run(): Promise<any> {
|
||||
this.historyService.forward(true);
|
||||
|
||||
return Promise.resolve(null);
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1330,7 +1338,7 @@ export class OpenPreviousRecentlyUsedEditorAction extends Action {
|
||||
run(): Promise<any> {
|
||||
this.historyService.back(true);
|
||||
|
||||
return Promise.resolve(null);
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as types from 'vs/base/common/types';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { TextCompareEditorVisibleContext, EditorInput, IEditorIdentifier, IEditorCommandsContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, CloseDirection, IEditor, IEditorInput } from 'vs/workbench/common/editor';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IEditorService, IVisibleEditor } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
||||
import { TextDiffEditor } from 'vs/workbench/browser/parts/editor/textDiffEditor';
|
||||
import { KeyMod, KeyCode, KeyChord } from 'vs/base/common/keyCodes';
|
||||
@@ -16,8 +16,8 @@ import { URI } from 'vs/base/common/uri';
|
||||
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
|
||||
import { IListService } from 'vs/platform/list/browser/listService';
|
||||
import { List } from 'vs/base/browser/ui/list/listWidget';
|
||||
import { distinct } from 'vs/base/common/arrays';
|
||||
import { IEditorGroupsService, IEditorGroup, GroupDirection, GroupLocation, GroupsOrder, preferredSideBySideGroupDirection, EditorGroupLayout } from 'vs/workbench/services/group/common/editorGroupsService';
|
||||
import { distinct, coalesce } from 'vs/base/common/arrays';
|
||||
import { IEditorGroupsService, IEditorGroup, GroupDirection, GroupLocation, GroupsOrder, preferredSideBySideGroupDirection, EditorGroupLayout } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
import { CommandsRegistry, ICommandHandler } from 'vs/platform/commands/common/commands';
|
||||
@@ -52,9 +52,9 @@ export const NAVIGATE_IN_ACTIVE_GROUP_PREFIX = 'edt active ';
|
||||
export const OPEN_EDITOR_AT_INDEX_COMMAND_ID = 'workbench.action.openEditorAtIndex';
|
||||
|
||||
export interface ActiveEditorMoveArguments {
|
||||
to?: 'first' | 'last' | 'left' | 'right' | 'up' | 'down' | 'center' | 'position' | 'previous' | 'next';
|
||||
by?: 'tab' | 'group';
|
||||
value?: number;
|
||||
to: 'first' | 'last' | 'left' | 'right' | 'up' | 'down' | 'center' | 'position' | 'previous' | 'next';
|
||||
by: 'tab' | 'group';
|
||||
value: number;
|
||||
}
|
||||
|
||||
const isActiveEditorMoveArg = function (arg: ActiveEditorMoveArguments): boolean {
|
||||
@@ -90,7 +90,24 @@ function registerActiveEditorMoveCommand(): void {
|
||||
{
|
||||
name: nls.localize('editorCommand.activeEditorMove.arg.name', "Active editor move argument"),
|
||||
description: nls.localize('editorCommand.activeEditorMove.arg.description', "Argument Properties:\n\t* 'to': String value providing where to move.\n\t* 'by': String value providing the unit for move (by tab or by group).\n\t* 'value': Number value providing how many positions or an absolute position to move."),
|
||||
constraint: isActiveEditorMoveArg
|
||||
constraint: isActiveEditorMoveArg,
|
||||
schema: {
|
||||
'type': 'object',
|
||||
'required': ['to'],
|
||||
'properties': {
|
||||
'to': {
|
||||
'type': 'string',
|
||||
'enum': ['left', 'right']
|
||||
},
|
||||
'by': {
|
||||
'type': 'string',
|
||||
'enum': ['tab', 'group']
|
||||
},
|
||||
'value': {
|
||||
'type': 'number'
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -113,7 +130,7 @@ function moveActiveEditor(args: ActiveEditorMoveArguments = Object.create(null),
|
||||
}
|
||||
}
|
||||
|
||||
function moveActiveTab(args: ActiveEditorMoveArguments, control: IEditor, accessor: ServicesAccessor): void {
|
||||
function moveActiveTab(args: ActiveEditorMoveArguments, control: IVisibleEditor, accessor: ServicesAccessor): void {
|
||||
const group = control.group;
|
||||
let index = group.getIndexOfEditor(control.input);
|
||||
switch (args.to) {
|
||||
@@ -141,12 +158,12 @@ function moveActiveTab(args: ActiveEditorMoveArguments, control: IEditor, access
|
||||
group.moveEditor(control.input, group, { index });
|
||||
}
|
||||
|
||||
function moveActiveEditorToGroup(args: ActiveEditorMoveArguments, control: IEditor, accessor: ServicesAccessor): void {
|
||||
function moveActiveEditorToGroup(args: ActiveEditorMoveArguments, control: IVisibleEditor, accessor: ServicesAccessor): void {
|
||||
const editorGroupService = accessor.get(IEditorGroupsService);
|
||||
const configurationService = accessor.get(IConfigurationService);
|
||||
|
||||
const sourceGroup = control.group;
|
||||
let targetGroup: IEditorGroup;
|
||||
let targetGroup: IEditorGroup | undefined;
|
||||
|
||||
switch (args.to) {
|
||||
case 'left':
|
||||
@@ -340,7 +357,7 @@ function registerOpenEditorAtIndexCommands(): void {
|
||||
case 9: return KeyCode.KEY_9;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
throw new Error('invalid index');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -392,7 +409,7 @@ function registerFocusEditorGroupAtIndexCommands(): void {
|
||||
case 7: return 'workbench.action.focusEighthEditorGroup';
|
||||
}
|
||||
|
||||
return undefined;
|
||||
throw new Error('Invalid index');
|
||||
}
|
||||
|
||||
function toKeyCode(index: number): KeyCode {
|
||||
@@ -406,23 +423,27 @@ function registerFocusEditorGroupAtIndexCommands(): void {
|
||||
case 7: return KeyCode.KEY_8;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
throw new Error('Invalid index');
|
||||
}
|
||||
}
|
||||
|
||||
export function splitEditor(editorGroupService: IEditorGroupsService, direction: GroupDirection, context?: IEditorCommandsContext): void {
|
||||
let sourceGroup: IEditorGroup;
|
||||
let sourceGroup: IEditorGroup | undefined;
|
||||
if (context && typeof context.groupId === 'number') {
|
||||
sourceGroup = editorGroupService.getGroup(context.groupId);
|
||||
} else {
|
||||
sourceGroup = editorGroupService.activeGroup;
|
||||
}
|
||||
|
||||
if (!sourceGroup) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Add group
|
||||
const newGroup = editorGroupService.addGroup(sourceGroup, direction);
|
||||
|
||||
// Split editor (if it can be split)
|
||||
let editorToCopy: IEditorInput;
|
||||
let editorToCopy: IEditorInput | null;
|
||||
if (context && typeof context.editorIndex === 'number') {
|
||||
editorToCopy = sourceGroup.getEditor(context.editorIndex);
|
||||
} else {
|
||||
@@ -466,9 +487,14 @@ function registerCloseEditorCommands() {
|
||||
contexts.push({ groupId: activeGroup.id }); // active group as fallback
|
||||
}
|
||||
|
||||
return Promise.all(distinct(contexts.map(c => c.groupId)).map(groupId =>
|
||||
editorGroupService.getGroup(groupId).closeEditors({ savedOnly: true })
|
||||
));
|
||||
return Promise.all(distinct(contexts.map(c => c.groupId)).map(groupId => {
|
||||
const group = editorGroupService.getGroup(groupId);
|
||||
if (group) {
|
||||
return group.closeEditors({ savedOnly: true });
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -486,9 +512,14 @@ function registerCloseEditorCommands() {
|
||||
distinctGroupIds.push(editorGroupService.activeGroup.id);
|
||||
}
|
||||
|
||||
return Promise.all(distinctGroupIds.map(groupId =>
|
||||
editorGroupService.getGroup(groupId).closeAllEditors()
|
||||
));
|
||||
return Promise.all(distinctGroupIds.map(groupId => {
|
||||
const group = editorGroupService.getGroup(groupId);
|
||||
if (group) {
|
||||
return group.closeAllEditors();
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -511,11 +542,15 @@ function registerCloseEditorCommands() {
|
||||
|
||||
return Promise.all(groupIds.map(groupId => {
|
||||
const group = editorGroupService.getGroup(groupId);
|
||||
const editors = contexts
|
||||
.filter(context => context.groupId === groupId)
|
||||
.map(context => typeof context.editorIndex === 'number' ? group.getEditor(context.editorIndex) : group.activeEditor);
|
||||
if (group) {
|
||||
const editors = coalesce(contexts
|
||||
.filter(context => context.groupId === groupId)
|
||||
.map(context => typeof context.editorIndex === 'number' ? group.getEditor(context.editorIndex) : group.activeEditor));
|
||||
|
||||
return group.closeEditors(editors);
|
||||
return group.closeEditors(editors);
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
}));
|
||||
}
|
||||
});
|
||||
@@ -530,14 +565,16 @@ function registerCloseEditorCommands() {
|
||||
const editorGroupService = accessor.get(IEditorGroupsService);
|
||||
const commandsContext = getCommandsContext(resourceOrContext, context);
|
||||
|
||||
let group: IEditorGroup;
|
||||
let group: IEditorGroup | undefined;
|
||||
if (commandsContext && typeof commandsContext.groupId === 'number') {
|
||||
group = editorGroupService.getGroup(commandsContext.groupId);
|
||||
} else {
|
||||
group = editorGroupService.activeGroup;
|
||||
}
|
||||
|
||||
editorGroupService.removeGroup(group);
|
||||
if (group) {
|
||||
editorGroupService.removeGroup(group);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -560,12 +597,16 @@ function registerCloseEditorCommands() {
|
||||
|
||||
return Promise.all(groupIds.map(groupId => {
|
||||
const group = editorGroupService.getGroup(groupId);
|
||||
const editors = contexts
|
||||
.filter(context => context.groupId === groupId)
|
||||
.map(context => typeof context.editorIndex === 'number' ? group.getEditor(context.editorIndex) : group.activeEditor);
|
||||
const editorsToClose = group.editors.filter(e => editors.indexOf(e) === -1);
|
||||
if (group) {
|
||||
const editors = contexts
|
||||
.filter(context => context.groupId === groupId)
|
||||
.map(context => typeof context.editorIndex === 'number' ? group.getEditor(context.editorIndex) : group.activeEditor);
|
||||
const editorsToClose = group.editors.filter(e => editors.indexOf(e) === -1);
|
||||
|
||||
return group.closeEditors(editorsToClose);
|
||||
return group.closeEditors(editorsToClose);
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
}));
|
||||
}
|
||||
});
|
||||
@@ -619,7 +660,10 @@ function registerCloseEditorCommands() {
|
||||
|
||||
const commandsContext = getCommandsContext(resourceOrContext, context);
|
||||
if (commandsContext && typeof commandsContext.groupId === 'number') {
|
||||
editorGroupService.activateGroup(editorGroupService.getGroup(commandsContext.groupId)); // we need the group to be active
|
||||
const group = editorGroupService.getGroup(commandsContext.groupId);
|
||||
if (group) {
|
||||
editorGroupService.activateGroup(group); // we need the group to be active
|
||||
}
|
||||
}
|
||||
|
||||
return quickOpenService.show(NAVIGATE_IN_ACTIVE_GROUP_PREFIX);
|
||||
@@ -642,7 +686,7 @@ function registerCloseEditorCommands() {
|
||||
});
|
||||
}
|
||||
|
||||
function getCommandsContext(resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext): IEditorCommandsContext {
|
||||
function getCommandsContext(resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext): IEditorCommandsContext | undefined {
|
||||
if (URI.isUri(resourceOrContext)) {
|
||||
return context;
|
||||
}
|
||||
@@ -658,11 +702,11 @@ function getCommandsContext(resourceOrContext: URI | IEditorCommandsContext, con
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function resolveCommandsContext(editorGroupService: IEditorGroupsService, context?: IEditorCommandsContext): { group: IEditorGroup, editor: IEditorInput, control: IEditor } {
|
||||
function resolveCommandsContext(editorGroupService: IEditorGroupsService, context?: IEditorCommandsContext): { group: IEditorGroup, editor?: IEditorInput, control?: IEditor } {
|
||||
|
||||
// Resolve from context
|
||||
let group = context && typeof context.groupId === 'number' ? editorGroupService.getGroup(context.groupId) : undefined;
|
||||
let editor = group && typeof context.editorIndex === 'number' ? group.getEditor(context.editorIndex) : undefined;
|
||||
let editor = group && context && typeof context.editorIndex === 'number' ? types.withNullAsUndefined(group.getEditor(context.editorIndex)) : undefined;
|
||||
let control = group ? group.activeControl : undefined;
|
||||
|
||||
// Fallback to active group as needed
|
||||
@@ -675,7 +719,7 @@ function resolveCommandsContext(editorGroupService: IEditorGroupsService, contex
|
||||
return { group, editor, control };
|
||||
}
|
||||
|
||||
export function getMultiSelectedEditorContexts(editorContext: IEditorCommandsContext, listService: IListService, editorGroupService: IEditorGroupsService): IEditorCommandsContext[] {
|
||||
export function getMultiSelectedEditorContexts(editorContext: IEditorCommandsContext | undefined, listService: IListService, editorGroupService: IEditorGroupsService): IEditorCommandsContext[] {
|
||||
|
||||
// First check for a focused list to return the selected items from
|
||||
const list = listService.lastFocusedList;
|
||||
@@ -685,7 +729,9 @@ export function getMultiSelectedEditorContexts(editorContext: IEditorCommandsCon
|
||||
return { groupId: element.id, editorIndex: undefined };
|
||||
}
|
||||
|
||||
return { groupId: element.groupId, editorIndex: editorGroupService.getGroup(element.groupId).getIndexOfEditor(element.editor) };
|
||||
const group = editorGroupService.getGroup(element.groupId);
|
||||
|
||||
return { groupId: element.groupId, editorIndex: group ? group.getIndexOfEditor(element.editor) : -1 };
|
||||
};
|
||||
|
||||
const onlyEditorGroupAndEditor = (e: IEditorIdentifier | IEditorGroup) => isEditorGroup(e) || isEditorIdentifier(e);
|
||||
@@ -697,7 +743,14 @@ export function getMultiSelectedEditorContexts(editorContext: IEditorCommandsCon
|
||||
const selection: Array<IEditorIdentifier | IEditorGroup> = list.getSelectedElements().filter(onlyEditorGroupAndEditor);
|
||||
|
||||
// Only respect selection if it contains focused element
|
||||
if (selection && selection.some(s => isEditorGroup(s) ? s.id === focus.groupId : s.groupId === focus.groupId && editorGroupService.getGroup(s.groupId).getIndexOfEditor(s.editor) === focus.editorIndex)) {
|
||||
if (selection && selection.some(s => {
|
||||
if (isEditorGroup(s)) {
|
||||
return s.id === focus.groupId;
|
||||
}
|
||||
|
||||
const group = editorGroupService.getGroup(s.groupId);
|
||||
return s.groupId === focus.groupId && (group ? group.getIndexOfEditor(s.editor) : -1) === focus.editorIndex;
|
||||
})) {
|
||||
return selection.map(elementToContext);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,12 +8,14 @@ import { EditorInput, EditorOptions } from 'vs/workbench/common/editor';
|
||||
import { Dimension, show, hide, addClass } from 'vs/base/browser/dom';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IEditorRegistry, Extensions as EditorExtensions, IEditorDescriptor } from 'vs/workbench/browser/editor';
|
||||
import { IPartService } from 'vs/workbench/services/part/common/partService';
|
||||
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IProgressService, LongRunningOperation } from 'vs/platform/progress/common/progress';
|
||||
import { IEditorGroupView, DEFAULT_EDITOR_MIN_DIMENSIONS, DEFAULT_EDITOR_MAX_DIMENSIONS } from 'vs/workbench/browser/parts/editor/editor';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { IVisibleEditor } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { withUndefinedAsNull } from 'vs/base/common/types';
|
||||
|
||||
export interface IOpenEditorResult {
|
||||
readonly control: BaseEditor;
|
||||
@@ -27,7 +29,7 @@ export class EditorControl extends Disposable {
|
||||
get maximumWidth() { return this._activeControl ? this._activeControl.maximumWidth : DEFAULT_EDITOR_MAX_DIMENSIONS.width; }
|
||||
get maximumHeight() { return this._activeControl ? this._activeControl.maximumHeight : DEFAULT_EDITOR_MAX_DIMENSIONS.height; }
|
||||
|
||||
private _onDidFocus: Emitter<void> = this._register(new Emitter<void>());
|
||||
private readonly _onDidFocus: Emitter<void> = this._register(new Emitter<void>());
|
||||
get onDidFocus(): Event<void> { return this._onDidFocus.event; }
|
||||
|
||||
private _onDidSizeConstraintsChange = this._register(new Emitter<{ width: number; height: number; } | undefined>());
|
||||
@@ -43,7 +45,7 @@ export class EditorControl extends Disposable {
|
||||
constructor(
|
||||
private parent: HTMLElement,
|
||||
private groupView: IEditorGroupView,
|
||||
@IPartService private readonly partService: IPartService,
|
||||
@IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IProgressService progressService: IProgressService
|
||||
) {
|
||||
@@ -52,8 +54,8 @@ export class EditorControl extends Disposable {
|
||||
this.editorOperation = this._register(new LongRunningOperation(progressService));
|
||||
}
|
||||
|
||||
get activeControl() {
|
||||
return this._activeControl;
|
||||
get activeControl(): IVisibleEditor | null {
|
||||
return this._activeControl as IVisibleEditor | null;
|
||||
}
|
||||
|
||||
openEditor(editor: EditorInput, options?: EditorOptions): Promise<IOpenEditorResult> {
|
||||
@@ -66,7 +68,7 @@ export class EditorControl extends Disposable {
|
||||
const control = this.doShowEditorControl(descriptor);
|
||||
|
||||
// Set input
|
||||
return this.doSetInput(control, editor, options || null).then((editorChanged => (({ control, editorChanged } as IOpenEditorResult))));
|
||||
return this.doSetInput(control, editor, withUndefinedAsNull(options)).then((editorChanged => (({ control, editorChanged } as IOpenEditorResult))));
|
||||
}
|
||||
|
||||
private doShowEditorControl(descriptor: IEditorDescriptor): BaseEditor {
|
||||
@@ -170,7 +172,7 @@ export class EditorControl extends Disposable {
|
||||
|
||||
// Show progress while setting input after a certain timeout. If the workbench is opening
|
||||
// be more relaxed about progress showing by increasing the delay a little bit to reduce flicker.
|
||||
const operation = this.editorOperation.start(this.partService.isRestored() ? 800 : 3200);
|
||||
const operation = this.editorOperation.start(this.layoutService.isRestored() ? 800 : 3200);
|
||||
|
||||
// Call into editor control
|
||||
const editorWillChange = !inputMatches;
|
||||
|
||||
@@ -12,7 +12,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { activeContrastBorder } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { IEditorIdentifier, EditorInput, EditorOptions } from 'vs/workbench/common/editor';
|
||||
import { isMacintosh } from 'vs/base/common/platform';
|
||||
import { GroupDirection, MergeGroupMode } from 'vs/workbench/services/group/common/editorGroupsService';
|
||||
import { GroupDirection, MergeGroupMode } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
@@ -28,7 +28,7 @@ class DropOverlay extends Themable {
|
||||
private container: HTMLElement;
|
||||
private overlay: HTMLElement;
|
||||
|
||||
private currentDropOperation: IDropOperation;
|
||||
private currentDropOperation?: IDropOperation;
|
||||
private _disposed: boolean;
|
||||
|
||||
private cleanupOverlayScheduler: RunOnceScheduler;
|
||||
@@ -103,12 +103,12 @@ class DropOverlay extends Themable {
|
||||
|
||||
// Update the dropEffect to "copy" if there is no local data to be dragged because
|
||||
// in that case we can only copy the data into and not move it from its source
|
||||
if (!isDraggingEditor && !isDraggingGroup) {
|
||||
if (!isDraggingEditor && !isDraggingGroup && e.dataTransfer) {
|
||||
e.dataTransfer.dropEffect = 'copy';
|
||||
}
|
||||
|
||||
// Find out if operation is valid
|
||||
const isCopy = isDraggingGroup ? this.isCopyOperation(e) : isDraggingEditor ? this.isCopyOperation(e, this.editorTransfer.getData(DraggedEditorIdentifier.prototype)[0].identifier) : true;
|
||||
const isCopy = isDraggingGroup ? this.isCopyOperation(e) : isDraggingEditor ? this.isCopyOperation(e, this.editorTransfer.getData(DraggedEditorIdentifier.prototype)![0].identifier) : true;
|
||||
if (!isCopy) {
|
||||
const sourceGroupView = this.findSourceGroupView();
|
||||
if (sourceGroupView === this.groupView) {
|
||||
@@ -158,16 +158,16 @@ class DropOverlay extends Themable {
|
||||
}));
|
||||
}
|
||||
|
||||
private findSourceGroupView(): IEditorGroupView {
|
||||
private findSourceGroupView(): IEditorGroupView | undefined {
|
||||
|
||||
// Check for group transfer
|
||||
if (this.groupTransfer.hasData(DraggedEditorGroupIdentifier.prototype)) {
|
||||
return this.accessor.getGroup(this.groupTransfer.getData(DraggedEditorGroupIdentifier.prototype)[0].identifier);
|
||||
return this.accessor.getGroup(this.groupTransfer.getData(DraggedEditorGroupIdentifier.prototype)![0].identifier);
|
||||
}
|
||||
|
||||
// Check for editor transfer
|
||||
else if (this.editorTransfer.hasData(DraggedEditorIdentifier.prototype)) {
|
||||
return this.accessor.getGroup(this.editorTransfer.getData(DraggedEditorIdentifier.prototype)[0].identifier.groupId);
|
||||
return this.accessor.getGroup(this.editorTransfer.getData(DraggedEditorIdentifier.prototype)![0].identifier.groupId);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
@@ -189,59 +189,66 @@ class DropOverlay extends Themable {
|
||||
|
||||
// Check for group transfer
|
||||
if (this.groupTransfer.hasData(DraggedEditorGroupIdentifier.prototype)) {
|
||||
const draggedEditorGroup = this.groupTransfer.getData(DraggedEditorGroupIdentifier.prototype)[0].identifier;
|
||||
const draggedEditorGroup = this.groupTransfer.getData(DraggedEditorGroupIdentifier.prototype)![0].identifier;
|
||||
|
||||
// Return if the drop is a no-op
|
||||
const sourceGroup = this.accessor.getGroup(draggedEditorGroup);
|
||||
if (typeof splitDirection !== 'number' && sourceGroup === this.groupView) {
|
||||
return;
|
||||
}
|
||||
if (sourceGroup) {
|
||||
if (typeof splitDirection !== 'number' && sourceGroup === this.groupView) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Split to new group
|
||||
let targetGroup: IEditorGroupView;
|
||||
if (typeof splitDirection === 'number') {
|
||||
if (this.isCopyOperation(event)) {
|
||||
targetGroup = this.accessor.copyGroup(sourceGroup, this.groupView, splitDirection);
|
||||
} else {
|
||||
targetGroup = this.accessor.moveGroup(sourceGroup, this.groupView, splitDirection);
|
||||
// Split to new group
|
||||
let targetGroup: IEditorGroupView | undefined;
|
||||
if (typeof splitDirection === 'number') {
|
||||
if (this.isCopyOperation(event)) {
|
||||
targetGroup = this.accessor.copyGroup(sourceGroup, this.groupView, splitDirection);
|
||||
} else {
|
||||
targetGroup = this.accessor.moveGroup(sourceGroup, this.groupView, splitDirection);
|
||||
}
|
||||
}
|
||||
|
||||
// Merge into existing group
|
||||
else {
|
||||
if (this.isCopyOperation(event)) {
|
||||
targetGroup = this.accessor.mergeGroup(sourceGroup, this.groupView, { mode: MergeGroupMode.COPY_EDITORS });
|
||||
} else {
|
||||
targetGroup = this.accessor.mergeGroup(sourceGroup, this.groupView);
|
||||
}
|
||||
}
|
||||
|
||||
if (targetGroup) {
|
||||
this.accessor.activateGroup(targetGroup);
|
||||
}
|
||||
}
|
||||
|
||||
// Merge into existing group
|
||||
else {
|
||||
if (this.isCopyOperation(event)) {
|
||||
targetGroup = this.accessor.mergeGroup(sourceGroup, this.groupView, { mode: MergeGroupMode.COPY_EDITORS });
|
||||
} else {
|
||||
targetGroup = this.accessor.mergeGroup(sourceGroup, this.groupView);
|
||||
}
|
||||
}
|
||||
|
||||
this.accessor.activateGroup(targetGroup);
|
||||
this.groupTransfer.clearData(DraggedEditorGroupIdentifier.prototype);
|
||||
}
|
||||
|
||||
// Check for editor transfer
|
||||
else if (this.editorTransfer.hasData(DraggedEditorIdentifier.prototype)) {
|
||||
const draggedEditor = this.editorTransfer.getData(DraggedEditorIdentifier.prototype)[0].identifier;
|
||||
const draggedEditor = this.editorTransfer.getData(DraggedEditorIdentifier.prototype)![0].identifier;
|
||||
const targetGroup = ensureTargetGroup();
|
||||
|
||||
// Return if the drop is a no-op
|
||||
const sourceGroup = this.accessor.getGroup(draggedEditor.groupId);
|
||||
if (sourceGroup === targetGroup) {
|
||||
return;
|
||||
}
|
||||
if (sourceGroup) {
|
||||
if (sourceGroup === targetGroup) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Open in target group
|
||||
const options = getActiveTextEditorOptions(sourceGroup, draggedEditor.editor, EditorOptions.create({ pinned: true }));
|
||||
targetGroup.openEditor(draggedEditor.editor, options);
|
||||
// Open in target group
|
||||
const options = getActiveTextEditorOptions(sourceGroup, draggedEditor.editor, EditorOptions.create({ pinned: true }));
|
||||
targetGroup.openEditor(draggedEditor.editor, options);
|
||||
|
||||
// Ensure target has focus
|
||||
targetGroup.focus();
|
||||
// Ensure target has focus
|
||||
targetGroup.focus();
|
||||
|
||||
// Close in source group unless we copy
|
||||
const copyEditor = this.isCopyOperation(event, draggedEditor);
|
||||
if (!copyEditor) {
|
||||
sourceGroup.closeEditor(draggedEditor.editor);
|
||||
// Close in source group unless we copy
|
||||
const copyEditor = this.isCopyOperation(event, draggedEditor);
|
||||
if (!copyEditor) {
|
||||
sourceGroup.closeEditor(draggedEditor.editor);
|
||||
}
|
||||
}
|
||||
|
||||
this.editorTransfer.clearData(DraggedEditorIdentifier.prototype);
|
||||
@@ -250,7 +257,7 @@ class DropOverlay extends Themable {
|
||||
// Check for URI transfer
|
||||
else {
|
||||
const dropHandler = this.instantiationService.createInstance(ResourcesDropHandler, { allowWorkspaceOpen: true /* open workspace instead of file if dropped */ });
|
||||
dropHandler.handleDrop(event, () => ensureTargetGroup(), targetGroup => targetGroup.focus());
|
||||
dropHandler.handleDrop(event, () => ensureTargetGroup(), targetGroup => targetGroup!.focus());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,7 +305,7 @@ class DropOverlay extends Themable {
|
||||
// child.style.top = edgeHeightThreshold + 'px';
|
||||
|
||||
// No split if mouse is above certain threshold in the center of the view
|
||||
let splitDirection: GroupDirection;
|
||||
let splitDirection: GroupDirection | undefined;
|
||||
if (
|
||||
mousePosX > edgeWidthThreshold && mousePosX < editorControlWidth - edgeWidthThreshold &&
|
||||
mousePosY > edgeHeightThreshold && mousePosY < editorControlHeight - edgeHeightThreshold
|
||||
@@ -429,7 +436,7 @@ class DropOverlay extends Themable {
|
||||
|
||||
export class EditorDropTarget extends Themable {
|
||||
|
||||
private _overlay: DropOverlay;
|
||||
private _overlay?: DropOverlay;
|
||||
|
||||
private counter = 0;
|
||||
|
||||
@@ -447,7 +454,7 @@ export class EditorDropTarget extends Themable {
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
private get overlay(): DropOverlay {
|
||||
private get overlay(): DropOverlay | undefined {
|
||||
if (this._overlay && !this._overlay.disposed) {
|
||||
return this._overlay;
|
||||
}
|
||||
@@ -468,7 +475,7 @@ export class EditorDropTarget extends Themable {
|
||||
if (
|
||||
!this.editorTransfer.hasData(DraggedEditorIdentifier.prototype) &&
|
||||
!this.groupTransfer.hasData(DraggedEditorGroupIdentifier.prototype) &&
|
||||
!event.dataTransfer.types.length // see https://github.com/Microsoft/vscode/issues/25789
|
||||
event.dataTransfer && !event.dataTransfer.types.length // see https://github.com/Microsoft/vscode/issues/25789
|
||||
) {
|
||||
event.dataTransfer.dropEffect = 'none';
|
||||
return; // unsupported transfer
|
||||
@@ -510,7 +517,7 @@ export class EditorDropTarget extends Themable {
|
||||
this.disposeOverlay();
|
||||
}
|
||||
|
||||
private findTargetGroupView(child: HTMLElement): IEditorGroupView {
|
||||
private findTargetGroupView(child: HTMLElement): IEditorGroupView | undefined {
|
||||
const groups = this.accessor.groups;
|
||||
for (const groupView of groups) {
|
||||
if (isAncestor(child, groupView.element)) {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./media/editorgroupview';
|
||||
|
||||
import { EditorGroup, IEditorOpenOptions, EditorCloseEvent, ISerializedEditorGroup, isSerializedEditorGroup } from 'vs/workbench/common/editor/editorGroup';
|
||||
import { EditorInput, EditorOptions, GroupIdentifier, ConfirmResult, SideBySideEditorInput, CloseDirection, IEditorCloseEvent, EditorGroupActiveEditorDirtyContext, IEditor } from 'vs/workbench/common/editor';
|
||||
import { Event, Emitter, Relay } from 'vs/base/common/event';
|
||||
@@ -16,12 +17,11 @@ import { attachProgressBarStyler } from 'vs/platform/theme/common/styler';
|
||||
import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
import { editorBackground, contrastBorder } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { Themable, EDITOR_GROUP_HEADER_TABS_BORDER, EDITOR_GROUP_HEADER_TABS_BACKGROUND, EDITOR_GROUP_HEADER_NO_TABS_BACKGROUND, EDITOR_GROUP_EMPTY_BACKGROUND, EDITOR_GROUP_FOCUSED_EMPTY_BORDER } from 'vs/workbench/common/theme';
|
||||
import { IMoveEditorOptions, ICopyEditorOptions, ICloseEditorsFilter, IGroupChangeEvent, GroupChangeKind, EditorsOrder, GroupsOrder } from 'vs/workbench/services/group/common/editorGroupsService';
|
||||
import { IMoveEditorOptions, ICopyEditorOptions, ICloseEditorsFilter, IGroupChangeEvent, GroupChangeKind, EditorsOrder, GroupsOrder, ICloseEditorOptions } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { TabsTitleControl } from 'vs/workbench/browser/parts/editor/tabsTitleControl';
|
||||
import { EditorControl } from 'vs/workbench/browser/parts/editor/editorControl';
|
||||
import { IProgressService } from 'vs/platform/progress/common/progress';
|
||||
import { ProgressService } from 'vs/workbench/services/progress/browser/progressService';
|
||||
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
|
||||
import { localize } from 'vs/nls';
|
||||
import { isPromiseCanceledError } from 'vs/base/common/errors';
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
@@ -33,7 +33,6 @@ import { EventType as TouchEventType, GestureEvent } from 'vs/base/browser/touch
|
||||
import { TitleControl } from 'vs/workbench/browser/parts/editor/titleControl';
|
||||
import { IEditorGroupsAccessor, IEditorGroupView, IEditorPartOptionsChangeEvent, getActiveTextEditorOptions, IEditorOpeningEvent } from 'vs/workbench/browser/parts/editor/editor';
|
||||
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
|
||||
import { join } from 'vs/base/common/paths';
|
||||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { ActionRunner, IAction, Action } from 'vs/base/common/actions';
|
||||
@@ -45,10 +44,14 @@ import { fillInContextMenuActions } from 'vs/platform/actions/browser/menuItemAc
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
// {{SQL CARBON EDIT}}
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { GlobalNewUntitledFileAction } from 'vs/workbench/parts/files/electron-browser/fileActions';
|
||||
import { GlobalNewUntitledFileAction } from 'vs/workbench/contrib/files/browser/fileActions';
|
||||
// {{SQL CARBON EDIT}} - End
|
||||
import { isErrorWithActions, IErrorWithActions } from 'vs/base/common/errorsWithActions';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IVisibleEditor } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
import { IHashService } from 'vs/workbench/services/hash/common/hashService';
|
||||
import { guessMimeTypes } from 'vs/base/common/mime';
|
||||
import { extname } from 'vs/base/common/path';
|
||||
|
||||
export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
|
||||
@@ -70,25 +73,25 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
|
||||
//#region events
|
||||
|
||||
private _onDidFocus: Emitter<void> = this._register(new Emitter<void>());
|
||||
private readonly _onDidFocus: Emitter<void> = this._register(new Emitter<void>());
|
||||
get onDidFocus(): Event<void> { return this._onDidFocus.event; }
|
||||
|
||||
private _onWillDispose: Emitter<void> = this._register(new Emitter<void>());
|
||||
private readonly _onWillDispose: Emitter<void> = this._register(new Emitter<void>());
|
||||
get onWillDispose(): Event<void> { return this._onWillDispose.event; }
|
||||
|
||||
private _onDidGroupChange: Emitter<IGroupChangeEvent> = this._register(new Emitter<IGroupChangeEvent>());
|
||||
private readonly _onDidGroupChange: Emitter<IGroupChangeEvent> = this._register(new Emitter<IGroupChangeEvent>());
|
||||
get onDidGroupChange(): Event<IGroupChangeEvent> { return this._onDidGroupChange.event; }
|
||||
|
||||
private _onWillOpenEditor: Emitter<IEditorOpeningEvent> = this._register(new Emitter<IEditorOpeningEvent>());
|
||||
private readonly _onWillOpenEditor: Emitter<IEditorOpeningEvent> = this._register(new Emitter<IEditorOpeningEvent>());
|
||||
get onWillOpenEditor(): Event<IEditorOpeningEvent> { return this._onWillOpenEditor.event; }
|
||||
|
||||
private _onDidOpenEditorFail: Emitter<EditorInput> = this._register(new Emitter<EditorInput>());
|
||||
private readonly _onDidOpenEditorFail: Emitter<EditorInput> = this._register(new Emitter<EditorInput>());
|
||||
get onDidOpenEditorFail(): Event<EditorInput> { return this._onDidOpenEditorFail.event; }
|
||||
|
||||
private _onWillCloseEditor: Emitter<IEditorCloseEvent> = this._register(new Emitter<IEditorCloseEvent>());
|
||||
private readonly _onWillCloseEditor: Emitter<IEditorCloseEvent> = this._register(new Emitter<IEditorCloseEvent>());
|
||||
get onWillCloseEditor(): Event<IEditorCloseEvent> { return this._onWillCloseEditor.event; }
|
||||
|
||||
private _onDidCloseEditor: Emitter<IEditorCloseEvent> = this._register(new Emitter<IEditorCloseEvent>());
|
||||
private readonly _onDidCloseEditor: Emitter<IEditorCloseEvent> = this._register(new Emitter<IEditorCloseEvent>());
|
||||
get onDidCloseEditor(): Event<IEditorCloseEvent> { return this._onDidCloseEditor.event; }
|
||||
|
||||
//#endregion
|
||||
@@ -112,7 +115,6 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
private editorContainer: HTMLElement;
|
||||
private editorControl: EditorControl;
|
||||
|
||||
private ignoreOpenEditorErrors: boolean;
|
||||
private disposedEditorsWorker: RunOnceWorker<EditorInput>;
|
||||
|
||||
private mapEditorToPendingConfirmation: Map<EditorInput, Promise<boolean>> = new Map<EditorInput, Promise<boolean>>();
|
||||
@@ -130,6 +132,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService,
|
||||
@IMenuService private readonly menuService: IMenuService,
|
||||
@IContextMenuService private readonly contextMenuService: IContextMenuService,
|
||||
@IHashService private readonly hashService: IHashService,
|
||||
// {{SQL CARBON EDIT}}
|
||||
@ICommandService private commandService: ICommandService
|
||||
) {
|
||||
@@ -417,6 +420,10 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
}
|
||||
|
||||
const activeEditor = this._group.activeEditor;
|
||||
if (!activeEditor) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
options.pinned = this._group.isPinned(activeEditor); // preserve pinned state
|
||||
options.preserveFocus = true; // handle focus after editor is opened
|
||||
|
||||
@@ -458,14 +465,18 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
}
|
||||
|
||||
private onDidEditorOpen(editor: EditorInput): void {
|
||||
/* __GDPR__
|
||||
"editorOpened" : {
|
||||
"${include}": [
|
||||
"${EditorTelemetryDescriptor}"
|
||||
]
|
||||
}
|
||||
*/
|
||||
this.telemetryService.publicLog('editorOpened', editor.getTelemetryDescriptor());
|
||||
|
||||
// Telemetry
|
||||
this.toEditorTelemetryDescriptor(editor).then(descriptor => {
|
||||
/* __GDPR__
|
||||
"editorOpened" : {
|
||||
"${include}": [
|
||||
"${EditorTelemetryDescriptor}"
|
||||
]
|
||||
}
|
||||
*/
|
||||
this.telemetryService.publicLog('editorOpened', descriptor);
|
||||
});
|
||||
|
||||
// Update container
|
||||
this.updateContainer();
|
||||
@@ -496,14 +507,17 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
}
|
||||
});
|
||||
|
||||
/* __GDPR__
|
||||
"editorClosed" : {
|
||||
"${include}": [
|
||||
"${EditorTelemetryDescriptor}"
|
||||
]
|
||||
}
|
||||
*/
|
||||
this.telemetryService.publicLog('editorClosed', event.editor.getTelemetryDescriptor());
|
||||
// Telemetry
|
||||
this.toEditorTelemetryDescriptor(event.editor).then(descriptor => {
|
||||
/* __GDPR__
|
||||
"editorClosed" : {
|
||||
"${include}": [
|
||||
"${EditorTelemetryDescriptor}"
|
||||
]
|
||||
}
|
||||
*/
|
||||
this.telemetryService.publicLog('editorClosed', descriptor);
|
||||
});
|
||||
|
||||
// Update container
|
||||
this.updateContainer();
|
||||
@@ -513,6 +527,26 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
this._onDidGroupChange.fire({ kind: GroupChangeKind.EDITOR_CLOSE, editor, editorIndex: event.index });
|
||||
}
|
||||
|
||||
private toEditorTelemetryDescriptor(editor: EditorInput): Thenable<object> {
|
||||
const descriptor = editor.getTelemetryDescriptor();
|
||||
|
||||
const resource = editor.getResource();
|
||||
if (resource && resource.fsPath) {
|
||||
return this.hashService.createSHA1(resource.fsPath).then(hashedPath => {
|
||||
descriptor['resource'] = { mimeType: guessMimeTypes(resource.fsPath).join(', '), scheme: resource.scheme, ext: extname(resource.fsPath), path: hashedPath };
|
||||
|
||||
/* __GDPR__FRAGMENT__
|
||||
"EditorTelemetryDescriptor" : {
|
||||
"resource": { "${inline}": [ "${URIDescriptor}" ] }
|
||||
}
|
||||
*/
|
||||
return descriptor;
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.resolve(descriptor);
|
||||
}
|
||||
|
||||
private onDidEditorDispose(editor: EditorInput): void {
|
||||
|
||||
// To prevent race conditions, we handle disposed editors in our worker with a timeout
|
||||
@@ -524,7 +558,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
private handleDisposedEditors(editors: EditorInput[]): void {
|
||||
|
||||
// Split between visible and hidden editors
|
||||
let activeEditor: EditorInput;
|
||||
let activeEditor: EditorInput | undefined;
|
||||
const inactiveEditors: EditorInput[] = [];
|
||||
editors.forEach(editor => {
|
||||
if (this._group.isActive(editor)) {
|
||||
@@ -567,7 +601,9 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
|
||||
// Pin preview editor once user disables preview
|
||||
if (event.oldPartOptions.enablePreview && !event.newPartOptions.enablePreview) {
|
||||
this.pinEditor(this._group.previewEditor);
|
||||
if (this._group.previewEditor) {
|
||||
this.pinEditor(this._group.previewEditor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -658,15 +694,15 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
return this._group.count;
|
||||
}
|
||||
|
||||
get activeControl(): BaseEditor {
|
||||
return this.editorControl ? this.editorControl.activeControl : undefined;
|
||||
get activeControl(): IVisibleEditor | undefined {
|
||||
return this.editorControl ? withNullAsUndefined(this.editorControl.activeControl) : undefined;
|
||||
}
|
||||
|
||||
get activeEditor(): EditorInput {
|
||||
get activeEditor(): EditorInput | null {
|
||||
return this._group.activeEditor;
|
||||
}
|
||||
|
||||
get previewEditor(): EditorInput {
|
||||
get previewEditor(): EditorInput | null {
|
||||
return this._group.previewEditor;
|
||||
}
|
||||
|
||||
@@ -686,7 +722,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
return this.editors;
|
||||
}
|
||||
|
||||
getEditor(index: number): EditorInput {
|
||||
getEditor(index: number): EditorInput | null {
|
||||
return this._group.getEditor(index);
|
||||
}
|
||||
|
||||
@@ -711,7 +747,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
this._onDidFocus.fire();
|
||||
}
|
||||
|
||||
pinEditor(editor: EditorInput = this.activeEditor): void {
|
||||
pinEditor(editor: EditorInput | undefined = this.activeEditor || undefined): void {
|
||||
if (editor && !this._group.isPinned(editor)) {
|
||||
|
||||
// Update model
|
||||
@@ -749,7 +785,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
return this.doOpenEditor(editor, options);
|
||||
}
|
||||
|
||||
private doOpenEditor(editor: EditorInput, options?: EditorOptions): Promise<IEditor> {
|
||||
private doOpenEditor(editor: EditorInput, options?: EditorOptions): Promise<IEditor | null> {
|
||||
|
||||
// Determine options
|
||||
const openEditorOptions: IEditorOpenOptions = {
|
||||
@@ -758,7 +794,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
active: this._group.count === 0 || !options || !options.inactive
|
||||
};
|
||||
|
||||
if (!openEditorOptions.active && !openEditorOptions.pinned && this._group.isPreview(this._group.activeEditor)) {
|
||||
if (!openEditorOptions.active && !openEditorOptions.pinned && this._group.activeEditor && this._group.isPreview(this._group.activeEditor)) {
|
||||
// Special case: we are to open an editor inactive and not pinned, but the current active
|
||||
// editor is also not pinned, which means it will get replaced with this one. As such,
|
||||
// the editor can only be active.
|
||||
@@ -787,13 +823,13 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
this._group.openEditor(editor, openEditorOptions);
|
||||
|
||||
// Show editor
|
||||
return this.doShowEditor(editor, openEditorOptions.active, options);
|
||||
return this.doShowEditor(editor, !!openEditorOptions.active, options);
|
||||
}
|
||||
|
||||
private doShowEditor(editor: EditorInput, active: boolean, options?: EditorOptions): Promise<IEditor> {
|
||||
private doShowEditor(editor: EditorInput, active: boolean, options?: EditorOptions): Promise<IEditor | null> {
|
||||
|
||||
// Show in editor control if the active editor changed
|
||||
let openEditorPromise: Promise<IEditor>;
|
||||
let openEditorPromise: Promise<IEditor | null>;
|
||||
if (active) {
|
||||
openEditorPromise = this.editorControl.openEditor(editor, options).then(result => {
|
||||
|
||||
@@ -824,7 +860,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
|
||||
// Report error only if this was not us restoring previous error state or
|
||||
// we are told to ignore errors that occur from opening an editor
|
||||
if (this.isRestored && !isPromiseCanceledError(error) && !this.ignoreOpenEditorErrors) {
|
||||
if (this.isRestored && !isPromiseCanceledError(error) && (!options || !options.ignoreError)) {
|
||||
const actions: INotificationActions = { primary: [] };
|
||||
if (isErrorWithActions(error)) {
|
||||
actions.primary = (error as IErrorWithActions).actions;
|
||||
@@ -836,7 +872,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
actions
|
||||
});
|
||||
|
||||
Event.once(handle.onDidClose)(() => dispose(actions.primary));
|
||||
Event.once(handle.onDidClose)(() => actions.primary && dispose(actions.primary));
|
||||
}
|
||||
|
||||
// Event
|
||||
@@ -861,10 +897,10 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
// Do not modify original array
|
||||
editors = editors.slice(0);
|
||||
|
||||
let result: IEditor;
|
||||
let result: IEditor | null;
|
||||
|
||||
// Use the first editor as active editor
|
||||
const { editor, options } = editors.shift();
|
||||
const { editor, options } = editors.shift()!;
|
||||
return this.openEditor(editor, options).then(activeEditor => {
|
||||
result = activeEditor; // this can be NULL if the opening failed
|
||||
|
||||
@@ -964,7 +1000,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
|
||||
//#region closeEditor()
|
||||
|
||||
closeEditor(editor: EditorInput = this.activeEditor): Promise<void> {
|
||||
closeEditor(editor: EditorInput | undefined = this.activeEditor || undefined, options?: ICloseEditorOptions): Promise<void> {
|
||||
if (!editor) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
@@ -976,11 +1012,11 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
}
|
||||
|
||||
// Do close
|
||||
this.doCloseEditor(editor);
|
||||
this.doCloseEditor(editor, options && options.preserveFocus ? false : undefined);
|
||||
});
|
||||
}
|
||||
|
||||
private doCloseEditor(editor: EditorInput, focusNext = this.accessor.activeGroup === this, fromError?: boolean): void {
|
||||
private doCloseEditor(editor: EditorInput, focusNext = (this.accessor.activeGroup === this), fromError?: boolean): void {
|
||||
|
||||
// Closing the active editor of the group is a bit more work
|
||||
if (this._group.isActive(editor)) {
|
||||
@@ -996,7 +1032,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
this.titleAreaControl.closeEditor(editor);
|
||||
}
|
||||
|
||||
private doCloseActiveEditor(focusNext = this.accessor.activeGroup === this, fromError?: boolean): void {
|
||||
private doCloseActiveEditor(focusNext = (this.accessor.activeGroup === this), fromError?: boolean): void {
|
||||
const editorToClose = this.activeEditor;
|
||||
const restoreFocus = this.shouldRestoreFocus(this.element);
|
||||
|
||||
@@ -1021,32 +1057,34 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
}
|
||||
|
||||
// Update model
|
||||
this._group.closeEditor(editorToClose);
|
||||
if (editorToClose) {
|
||||
this._group.closeEditor(editorToClose);
|
||||
}
|
||||
|
||||
// Open next active if there are more to show
|
||||
const nextActiveEditor = this._group.activeEditor;
|
||||
if (nextActiveEditor) {
|
||||
const options = EditorOptions.create({ preserveFocus: !focusNext });
|
||||
|
||||
// When closing an editor due to an error we can end up in a loop where we continue closing
|
||||
// editors that fail to open (e.g. when the file no longer exists). We do not want to show
|
||||
// repeated errors in this case to the user. As such, if we open the next editor and we are
|
||||
// in a scope of a previous editor failing, we silence the input errors until the editor is
|
||||
// opened.
|
||||
// opened by setting ignoreError: true.
|
||||
if (fromError) {
|
||||
this.ignoreOpenEditorErrors = true;
|
||||
options.ignoreError = true;
|
||||
}
|
||||
|
||||
const options = !focusNext ? EditorOptions.create({ preserveFocus: true }) : undefined;
|
||||
this.openEditor(nextActiveEditor, options).then(() => {
|
||||
this.ignoreOpenEditorErrors = false;
|
||||
});
|
||||
this.openEditor(nextActiveEditor, options);
|
||||
}
|
||||
|
||||
// Otherwise we are empty, so clear from editor control and send event
|
||||
else {
|
||||
|
||||
// Forward to editor control
|
||||
this.editorControl.closeEditor(editorToClose);
|
||||
if (editorToClose) {
|
||||
this.editorControl.closeEditor(editorToClose);
|
||||
}
|
||||
|
||||
// Restore focus to group container as needed unless group gets closed
|
||||
if (restoreFocus && !closeEmptyGroup) {
|
||||
@@ -1085,7 +1123,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
return Promise.resolve(false); // no veto
|
||||
}
|
||||
|
||||
const editor = editors.shift();
|
||||
const editor = editors.shift()!;
|
||||
|
||||
// To prevent multiple confirmation dialogs from showing up one after the other
|
||||
// we check if a pending confirmation is currently showing and if so, join that
|
||||
@@ -1157,7 +1195,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
|
||||
//#region closeEditors()
|
||||
|
||||
closeEditors(args: EditorInput[] | ICloseEditorsFilter): Promise<void> {
|
||||
closeEditors(args: EditorInput[] | ICloseEditorsFilter, options?: ICloseEditorOptions): Promise<void> {
|
||||
if (this.isEmpty()) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
@@ -1171,7 +1209,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
}
|
||||
|
||||
// Do close
|
||||
this.doCloseEditors(editors);
|
||||
this.doCloseEditors(editors, options);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1205,7 +1243,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
return editorsToClose;
|
||||
}
|
||||
|
||||
private doCloseEditors(editors: EditorInput[]): void {
|
||||
private doCloseEditors(editors: EditorInput[], options?: ICloseEditorOptions): void {
|
||||
|
||||
// Close all inactive editors first
|
||||
let closeActiveEditor = false;
|
||||
@@ -1219,7 +1257,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
|
||||
// Close active editor last if contained in editors list to close
|
||||
if (closeActiveEditor) {
|
||||
this.doCloseActiveEditor();
|
||||
this.doCloseActiveEditor(options && options.preserveFocus ? false : undefined);
|
||||
}
|
||||
|
||||
// Forward to title control
|
||||
@@ -1278,7 +1316,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
replaceEditors(editors: EditorReplacement[]): Promise<void> {
|
||||
|
||||
// Extract active vs. inactive replacements
|
||||
let activeReplacement: EditorReplacement;
|
||||
let activeReplacement: EditorReplacement | undefined;
|
||||
const inactiveReplacements: EditorReplacement[] = [];
|
||||
editors.forEach(({ editor, replacement, options }) => {
|
||||
if (editor.isDirty()) {
|
||||
@@ -1314,11 +1352,11 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
// Open inactive editor
|
||||
this.doOpenEditor(replacement, options);
|
||||
|
||||
// Close replaced inactive edior
|
||||
this.doCloseInactiveEditor(editor);
|
||||
|
||||
// Forward to title control
|
||||
this.titleAreaControl.closeEditor(editor);
|
||||
// Close replaced inactive editor unless they match
|
||||
if (!editor.matches(replacement)) {
|
||||
this.doCloseInactiveEditor(editor);
|
||||
this.titleAreaControl.closeEditor(editor);
|
||||
}
|
||||
});
|
||||
|
||||
// Handle active last
|
||||
@@ -1327,11 +1365,11 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
// Open replacement as active editor
|
||||
const openEditorResult = this.doOpenEditor(activeReplacement.replacement, activeReplacement.options);
|
||||
|
||||
// Close previous active editor
|
||||
this.doCloseInactiveEditor(activeReplacement.editor);
|
||||
|
||||
// Forward to title control
|
||||
this.titleAreaControl.closeEditor(activeReplacement.editor);
|
||||
// Close replaced active editor unless they match
|
||||
if (!activeReplacement.editor.matches(activeReplacement.replacement)) {
|
||||
this.doCloseInactiveEditor(activeReplacement.editor);
|
||||
this.titleAreaControl.closeEditor(activeReplacement.editor);
|
||||
}
|
||||
|
||||
return openEditorResult.then(() => undefined);
|
||||
}
|
||||
@@ -1384,8 +1422,8 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
get maximumWidth(): number { return this.editorControl.maximumWidth; }
|
||||
get maximumHeight(): number { return this.editorControl.maximumHeight; }
|
||||
|
||||
private _onDidChange = this._register(new Relay<{ width: number; height: number; }>());
|
||||
readonly onDidChange: Event<{ width: number; height: number; }> = this._onDidChange.event;
|
||||
private _onDidChange = this._register(new Relay<{ width: number; height: number; } | undefined>());
|
||||
readonly onDidChange: Event<{ width: number; height: number; } | undefined> = this._onDidChange.event;
|
||||
|
||||
layout(width: number, height: number): void {
|
||||
this.dimension = new Dimension(width, height);
|
||||
@@ -1430,7 +1468,7 @@ class EditorOpeningEvent implements IEditorOpeningEvent {
|
||||
constructor(
|
||||
private _group: GroupIdentifier,
|
||||
private _editor: EditorInput,
|
||||
private _options: EditorOptions
|
||||
private _options: EditorOptions | undefined
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -1442,7 +1480,7 @@ class EditorOpeningEvent implements IEditorOpeningEvent {
|
||||
return this._editor;
|
||||
}
|
||||
|
||||
get options(): EditorOptions {
|
||||
get options(): EditorOptions | undefined {
|
||||
return this._options;
|
||||
}
|
||||
|
||||
@@ -1464,10 +1502,10 @@ export interface EditorReplacement {
|
||||
registerThemingParticipant((theme, collector, environment) => {
|
||||
|
||||
// Letterpress
|
||||
const letterpress = `resources/letterpress${theme.type === 'dark' ? '-dark' : theme.type === 'hc' ? '-hc' : ''}.svg`;
|
||||
const letterpress = `./media/letterpress${theme.type === 'dark' ? '-dark' : theme.type === 'hc' ? '-hc' : ''}.svg`;
|
||||
collector.addRule(`
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.empty .editor-group-letterpress {
|
||||
background-image: url('${URI.file(join(environment.appRoot, letterpress)).toString()}')
|
||||
background-image: url('${require.toUrl(letterpress)}')
|
||||
}
|
||||
`);
|
||||
|
||||
|
||||
@@ -9,14 +9,14 @@ import { Part } from 'vs/workbench/browser/part';
|
||||
import { Dimension, isAncestor, toggleClass, addClass, $ } from 'vs/base/browser/dom';
|
||||
import { Event, Emitter, Relay } from 'vs/base/common/event';
|
||||
import { contrastBorder, editorBackground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { GroupDirection, IAddGroupOptions, GroupsArrangement, GroupOrientation, IMergeGroupOptions, MergeGroupMode, ICopyEditorOptions, GroupsOrder, GroupChangeKind, GroupLocation, IFindGroupScope, EditorGroupLayout, GroupLayoutArgument } from 'vs/workbench/services/group/common/editorGroupsService';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { Direction, SerializableGrid, Sizing, ISerializedGrid, Orientation, GridBranchNode, isGridBranchNode, GridNode, createSerializedGrid, Grid, ISerializableView } from 'vs/base/browser/ui/grid/grid';
|
||||
import { GroupIdentifier, IWorkbenchEditorConfiguration } from 'vs/workbench/common/editor';
|
||||
import { GroupDirection, IAddGroupOptions, GroupsArrangement, GroupOrientation, IMergeGroupOptions, MergeGroupMode, ICopyEditorOptions, GroupsOrder, GroupChangeKind, GroupLocation, IFindGroupScope, EditorGroupLayout, GroupLayoutArgument, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IInstantiationService, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { Direction, SerializableGrid, Sizing, ISerializedGrid, Orientation, GridBranchNode, isGridBranchNode, GridNode, createSerializedGrid, Grid } from 'vs/base/browser/ui/grid/grid';
|
||||
import { GroupIdentifier, IWorkbenchEditorConfiguration, IEditorPartOptions } from 'vs/workbench/common/editor';
|
||||
import { values } from 'vs/base/common/map';
|
||||
import { EDITOR_GROUP_BORDER, EDITOR_PANE_BACKGROUND } from 'vs/workbench/common/theme';
|
||||
import { distinct } from 'vs/base/common/arrays';
|
||||
import { IEditorGroupsAccessor, IEditorGroupView, IEditorPartOptions, getEditorPartOptions, impactsEditorPartOptions, IEditorPartOptionsChangeEvent, EditorGroupsServiceImpl } from 'vs/workbench/browser/parts/editor/editor';
|
||||
import { distinct, coalesce } from 'vs/base/common/arrays';
|
||||
import { IEditorGroupsAccessor, IEditorGroupView, getEditorPartOptions, impactsEditorPartOptions, IEditorPartOptionsChangeEvent, IEditorPartCreationOptions } from 'vs/workbench/browser/parts/editor/editor';
|
||||
import { EditorGroupView } from 'vs/workbench/browser/parts/editor/editorGroupView';
|
||||
import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration';
|
||||
import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
|
||||
@@ -29,7 +29,8 @@ import { Color } from 'vs/base/common/color';
|
||||
import { CenteredViewLayout } from 'vs/base/browser/ui/centered/centeredViewLayout';
|
||||
import { IView, orthogonal, LayoutPriority } from 'vs/base/browser/ui/grid/gridview';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { Parts } from 'vs/workbench/services/part/common/partService';
|
||||
import { Parts, IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
import { convertEditorInput } from 'sql/parts/common/customInputConverter';
|
||||
@@ -50,8 +51,8 @@ class GridWidgetView<T extends IView> implements IView {
|
||||
get minimumHeight(): number { return this.gridWidget ? this.gridWidget.minimumHeight : 0; }
|
||||
get maximumHeight(): number { return this.gridWidget ? this.gridWidget.maximumHeight : Number.POSITIVE_INFINITY; }
|
||||
|
||||
private _onDidChange = new Relay<{ width: number; height: number; }>();
|
||||
readonly onDidChange: Event<{ width: number; height: number; }> = this._onDidChange.event;
|
||||
private _onDidChange = new Relay<{ width: number; height: number; } | undefined>();
|
||||
readonly onDidChange: Event<{ width: number; height: number; } | undefined> = this._onDidChange.event;
|
||||
|
||||
private _gridWidget: Grid<T>;
|
||||
|
||||
@@ -83,44 +84,43 @@ class GridWidgetView<T extends IView> implements IView {
|
||||
}
|
||||
}
|
||||
|
||||
export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditorGroupsAccessor, ISerializableView {
|
||||
export class EditorPart extends Part implements IEditorGroupsService, IEditorGroupsAccessor {
|
||||
|
||||
_serviceBrand: any;
|
||||
_serviceBrand: ServiceIdentifier<any>;
|
||||
|
||||
private static readonly EDITOR_PART_UI_STATE_STORAGE_KEY = 'editorpart.state';
|
||||
private static readonly EDITOR_PART_CENTERED_VIEW_STORAGE_KEY = 'editorpart.centeredview';
|
||||
|
||||
//#region Events
|
||||
|
||||
private _onDidLayout: Emitter<Dimension> = this._register(new Emitter<Dimension>());
|
||||
private readonly _onDidLayout: Emitter<Dimension> = this._register(new Emitter<Dimension>());
|
||||
get onDidLayout(): Event<Dimension> { return this._onDidLayout.event; }
|
||||
|
||||
private _onDidActiveGroupChange: Emitter<IEditorGroupView> = this._register(new Emitter<IEditorGroupView>());
|
||||
private readonly _onDidActiveGroupChange: Emitter<IEditorGroupView> = this._register(new Emitter<IEditorGroupView>());
|
||||
get onDidActiveGroupChange(): Event<IEditorGroupView> { return this._onDidActiveGroupChange.event; }
|
||||
|
||||
private _onDidAddGroup: Emitter<IEditorGroupView> = this._register(new Emitter<IEditorGroupView>());
|
||||
private readonly _onDidActivateGroup: Emitter<IEditorGroupView> = this._register(new Emitter<IEditorGroupView>());
|
||||
get onDidActivateGroup(): Event<IEditorGroupView> { return this._onDidActivateGroup.event; }
|
||||
|
||||
private readonly _onDidAddGroup: Emitter<IEditorGroupView> = this._register(new Emitter<IEditorGroupView>());
|
||||
get onDidAddGroup(): Event<IEditorGroupView> { return this._onDidAddGroup.event; }
|
||||
|
||||
private _onDidRemoveGroup: Emitter<IEditorGroupView> = this._register(new Emitter<IEditorGroupView>());
|
||||
private readonly _onDidRemoveGroup: Emitter<IEditorGroupView> = this._register(new Emitter<IEditorGroupView>());
|
||||
get onDidRemoveGroup(): Event<IEditorGroupView> { return this._onDidRemoveGroup.event; }
|
||||
|
||||
private _onDidMoveGroup: Emitter<IEditorGroupView> = this._register(new Emitter<IEditorGroupView>());
|
||||
private readonly _onDidMoveGroup: Emitter<IEditorGroupView> = this._register(new Emitter<IEditorGroupView>());
|
||||
get onDidMoveGroup(): Event<IEditorGroupView> { return this._onDidMoveGroup.event; }
|
||||
|
||||
private onDidSetGridWidget = this._register(new Emitter<{ width: number; height: number; }>());
|
||||
private _onDidSizeConstraintsChange = this._register(new Relay<{ width: number; height: number; }>());
|
||||
get onDidSizeConstraintsChange(): Event<{ width: number; height: number; }> { return Event.any(this.onDidSetGridWidget.event, this._onDidSizeConstraintsChange.event); }
|
||||
private onDidSetGridWidget = this._register(new Emitter<{ width: number; height: number; } | undefined>());
|
||||
private _onDidSizeConstraintsChange = this._register(new Relay<{ width: number; height: number; } | undefined>());
|
||||
get onDidSizeConstraintsChange(): Event<{ width: number; height: number; } | undefined> { return Event.any(this.onDidSetGridWidget.event, this._onDidSizeConstraintsChange.event); }
|
||||
|
||||
private _onDidPreferredSizeChange: Emitter<void> = this._register(new Emitter<void>());
|
||||
private readonly _onDidPreferredSizeChange: Emitter<void> = this._register(new Emitter<void>());
|
||||
get onDidPreferredSizeChange(): Event<void> { return this._onDidPreferredSizeChange.event; }
|
||||
|
||||
private _onDidActivateGroup: Emitter<IEditorGroupView> = this._register(new Emitter<IEditorGroupView>());
|
||||
get onDidActivateGroup(): Event<IEditorGroupView> { return this._onDidActivateGroup.event; }
|
||||
|
||||
//#endregion
|
||||
|
||||
private dimension: Dimension;
|
||||
private _preferredSize: Dimension;
|
||||
private _preferredSize: Dimension | undefined;
|
||||
|
||||
private workspaceMemento: object;
|
||||
private globalMemento: object;
|
||||
@@ -139,22 +139,14 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
private _whenRestored: Promise<void>;
|
||||
private whenRestoredResolve: () => void;
|
||||
|
||||
element: HTMLElement;
|
||||
|
||||
private _onDidChange = new Emitter<{ width: number; height: number; }>();
|
||||
readonly onDidChange = this._onDidChange.event;
|
||||
|
||||
priority: LayoutPriority = LayoutPriority.High;
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
private restorePreviousState: boolean,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IStorageService storageService: IStorageService
|
||||
@IStorageService storageService: IStorageService,
|
||||
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService
|
||||
) {
|
||||
super(id, { hasTitle: false }, themeService, storageService);
|
||||
super(Parts.EDITOR_PART, { hasTitle: false }, themeService, storageService, layoutService);
|
||||
|
||||
this.gridWidgetView = new GridWidgetView<IEditorGroupView>();
|
||||
|
||||
@@ -172,7 +164,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
|
||||
private enforcedPartOptions: IEditorPartOptions[] = [];
|
||||
|
||||
private _onDidEditorPartOptionsChange: Emitter<IEditorPartOptionsChangeEvent> = this._register(new Emitter<IEditorPartOptionsChangeEvent>());
|
||||
private readonly _onDidEditorPartOptionsChange: Emitter<IEditorPartOptionsChangeEvent> = this._register(new Emitter<IEditorPartOptionsChangeEvent>());
|
||||
get onDidEditorPartOptionsChange(): Event<IEditorPartOptionsChangeEvent> { return this._onDidEditorPartOptionsChange.event; }
|
||||
|
||||
private registerListeners(): void {
|
||||
@@ -216,6 +208,9 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
|
||||
//#region IEditorGroupsService
|
||||
|
||||
private _dimension: Dimension;
|
||||
get dimension(): Dimension { return this._dimension; }
|
||||
|
||||
get activeGroup(): IEditorGroupView {
|
||||
return this._activeGroup;
|
||||
}
|
||||
@@ -229,11 +224,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
}
|
||||
|
||||
get orientation(): GroupOrientation {
|
||||
if (!this.gridWidget) {
|
||||
return undefined; // we have not been created yet
|
||||
}
|
||||
|
||||
return this.gridWidget.orientation === Orientation.VERTICAL ? GroupOrientation.VERTICAL : GroupOrientation.HORIZONTAL;
|
||||
return (this.gridWidget && this.gridWidget.orientation === Orientation.VERTICAL) ? GroupOrientation.VERTICAL : GroupOrientation.HORIZONTAL;
|
||||
}
|
||||
|
||||
get whenRestored(): Promise<void> {
|
||||
@@ -246,7 +237,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
return this.groups;
|
||||
|
||||
case GroupsOrder.MOST_RECENTLY_ACTIVE:
|
||||
const mostRecentActive = this.mostRecentActiveGroups.map(groupId => this.getGroup(groupId));
|
||||
const mostRecentActive = coalesce(this.mostRecentActiveGroups.map(groupId => this.getGroup(groupId)));
|
||||
|
||||
// there can be groups that got never active, even though they exist. in this case
|
||||
// make sure to ust append them at the end so that all groups are returned properly
|
||||
@@ -270,7 +261,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
}
|
||||
}
|
||||
|
||||
getGroup(identifier: GroupIdentifier): IEditorGroupView {
|
||||
getGroup(identifier: GroupIdentifier): IEditorGroupView | undefined {
|
||||
return this.groupViews.get(identifier);
|
||||
}
|
||||
|
||||
@@ -282,7 +273,11 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
}
|
||||
|
||||
// by location
|
||||
return this.doFindGroupByLocation(scope.location, source, wrap);
|
||||
if (typeof scope.location === 'number') {
|
||||
return this.doFindGroupByLocation(scope.location, source, wrap);
|
||||
}
|
||||
|
||||
throw new Error('invalid arguments');
|
||||
}
|
||||
|
||||
private doFindGroupByDirection(direction: GroupDirection, source: IEditorGroupView | GroupIdentifier, wrap?: boolean): IEditorGroupView {
|
||||
@@ -422,7 +417,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
this.doCreateGridControlWithState(gridDescriptor, activeGroup.id, currentGroupViews);
|
||||
|
||||
// Layout
|
||||
this.doLayout(this.dimension);
|
||||
this.doLayout(this._dimension);
|
||||
|
||||
// Update container
|
||||
this.updateContainer();
|
||||
@@ -506,7 +501,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
return newGroupView;
|
||||
}
|
||||
|
||||
private doCreateGroupView(from?: IEditorGroupView | ISerializedEditorGroup): IEditorGroupView {
|
||||
private doCreateGroupView(from?: IEditorGroupView | ISerializedEditorGroup | null): IEditorGroupView {
|
||||
|
||||
// Label: just use the number of existing groups as label
|
||||
const label = this.getGroupLabel(this.count + 1);
|
||||
@@ -601,7 +596,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
}
|
||||
}
|
||||
|
||||
private toGridViewOrientation(orientation: GroupOrientation, fallback?: Orientation): Orientation {
|
||||
private toGridViewOrientation(orientation: GroupOrientation, fallback: Orientation): Orientation {
|
||||
if (typeof orientation === 'number') {
|
||||
return orientation === GroupOrientation.HORIZONTAL ? Orientation.HORIZONTAL : Orientation.VERTICAL;
|
||||
}
|
||||
@@ -742,21 +737,26 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
}
|
||||
|
||||
private assertGroupView(group: IEditorGroupView | GroupIdentifier): IEditorGroupView {
|
||||
let groupView: IEditorGroupView | undefined;
|
||||
if (typeof group === 'number') {
|
||||
group = this.getGroup(group);
|
||||
groupView = this.getGroup(group);
|
||||
} else {
|
||||
groupView = group;
|
||||
}
|
||||
|
||||
if (!group) {
|
||||
if (!groupView) {
|
||||
throw new Error('Invalid editor group provided!');
|
||||
}
|
||||
|
||||
return group;
|
||||
return groupView;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Part
|
||||
|
||||
readonly priority: LayoutPriority = LayoutPriority.High;
|
||||
|
||||
get minimumWidth(): number { return this.centeredLayoutWidget.minimumWidth; }
|
||||
get maximumWidth(): number { return this.centeredLayoutWidget.maximumWidth; }
|
||||
get minimumHeight(): number { return this.centeredLayoutWidget.minimumHeight; }
|
||||
@@ -783,7 +783,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
return this.theme.getColor(EDITOR_GROUP_BORDER) || this.theme.getColor(contrastBorder) || Color.transparent;
|
||||
}
|
||||
|
||||
protected updateStyles(): void {
|
||||
updateStyles(): void {
|
||||
this.container.style.backgroundColor = this.getColor(editorBackground);
|
||||
|
||||
const separatorBorderStyle = { separatorBorder: this.gridSeparatorBorder, background: this.theme.getColor(EDITOR_PANE_BACKGROUND) || Color.transparent };
|
||||
@@ -791,7 +791,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
this.centeredLayoutWidget.styles(separatorBorderStyle);
|
||||
}
|
||||
|
||||
createContentArea(parent: HTMLElement): HTMLElement {
|
||||
createContentArea(parent: HTMLElement, options?: IEditorPartCreationOptions): HTMLElement {
|
||||
|
||||
// Container
|
||||
this.element = parent;
|
||||
@@ -800,7 +800,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
parent.appendChild(this.container);
|
||||
|
||||
// Grid control with center layout
|
||||
this.doCreateGridControl();
|
||||
this.doCreateGridControl(options);
|
||||
|
||||
this.centeredLayoutWidget = this._register(new CenteredViewLayout(this.container, this.gridWidgetView, this.globalMemento[EditorPart.EDITOR_PART_CENTERED_VIEW_STORAGE_KEY]));
|
||||
|
||||
@@ -819,15 +819,16 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
return this.centeredLayoutWidget.isActive();
|
||||
}
|
||||
|
||||
private doCreateGridControl(): void {
|
||||
private doCreateGridControl(options?: IEditorPartCreationOptions): void {
|
||||
|
||||
// Grid Widget (with previous UI state)
|
||||
if (this.restorePreviousState) {
|
||||
this.doCreateGridControlWithPreviousState();
|
||||
let restoreError = false;
|
||||
if (!options || options.restorePreviousState) {
|
||||
restoreError = !this.doCreateGridControlWithPreviousState();
|
||||
}
|
||||
|
||||
// Grid Widget (no previous UI state or failed to restore)
|
||||
if (!this.gridWidget) {
|
||||
if (!this.gridWidget || restoreError) {
|
||||
const initialGroup = this.doCreateGroupView();
|
||||
this.doSetGridWidget(new SerializableGrid(initialGroup));
|
||||
|
||||
@@ -842,7 +843,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
this.updateContainer();
|
||||
}
|
||||
|
||||
private doCreateGridControlWithPreviousState(): void {
|
||||
private doCreateGridControlWithPreviousState(): boolean {
|
||||
const uiState = this.workspaceMemento[EditorPart.EDITOR_PART_UI_STATE_STORAGE_KEY] as IEditorPartUIState;
|
||||
if (uiState && uiState.serializedGrid) {
|
||||
try {
|
||||
@@ -856,25 +857,20 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
// Ensure last active group has focus
|
||||
this._activeGroup.focus();
|
||||
} catch (error) {
|
||||
this.handleGridRestoreError(error, uiState);
|
||||
|
||||
// Log error
|
||||
onUnexpectedError(new Error(`Error restoring editor grid widget: ${error} (with state: ${JSON.stringify(uiState)})`));
|
||||
|
||||
// Clear any state we have from the failing restore
|
||||
this.groupViews.forEach(group => group.dispose());
|
||||
this.groupViews.clear();
|
||||
this.mostRecentActiveGroups = [];
|
||||
|
||||
return false; // failure
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private handleGridRestoreError(error: Error, state: IEditorPartUIState): void {
|
||||
|
||||
// Log error
|
||||
onUnexpectedError(new Error(`Error restoring editor grid widget: ${error} (with state: ${JSON.stringify(state)})`));
|
||||
|
||||
// Clear any state we have from the failing restore
|
||||
if (this.gridWidget) {
|
||||
this.doSetGridWidget();
|
||||
}
|
||||
|
||||
this.groupViews.forEach(group => group.dispose());
|
||||
this.groupViews.clear();
|
||||
this._activeGroup = undefined;
|
||||
this.mostRecentActiveGroups = [];
|
||||
return true; // success
|
||||
}
|
||||
|
||||
private doCreateGridControlWithState(serializedGrid: ISerializedGrid, activeGroupId: GroupIdentifier, editorGroupViewsToReuse?: IEditorGroupView[]): void {
|
||||
@@ -893,7 +889,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
fromJSON: (serializedEditorGroup: ISerializedEditorGroup | null) => {
|
||||
let groupView: IEditorGroupView;
|
||||
if (reuseGroupViews.length > 0) {
|
||||
groupView = reuseGroupViews.shift();
|
||||
groupView = reuseGroupViews.shift()!;
|
||||
} else {
|
||||
groupView = this.doCreateGroupView(serializedEditorGroup);
|
||||
}
|
||||
@@ -924,7 +920,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
this.doSetGridWidget(gridWidget);
|
||||
}
|
||||
|
||||
private doSetGridWidget(gridWidget?: SerializableGrid<IEditorGroupView>): void {
|
||||
private doSetGridWidget(gridWidget: SerializableGrid<IEditorGroupView>): void {
|
||||
if (this.gridWidget) {
|
||||
this.gridWidget.dispose();
|
||||
}
|
||||
@@ -932,9 +928,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
this.gridWidget = gridWidget;
|
||||
this.gridWidgetView.gridWidget = gridWidget;
|
||||
|
||||
if (gridWidget) {
|
||||
this._onDidSizeConstraintsChange.input = gridWidget.onDidChange;
|
||||
}
|
||||
this._onDidSizeConstraintsChange.input = gridWidget.onDidChange;
|
||||
|
||||
this.onDidSetGridWidget.fire(undefined);
|
||||
}
|
||||
@@ -962,23 +956,20 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
return this.groupViews.size === 1 && this._activeGroup.isEmpty();
|
||||
}
|
||||
|
||||
layout(dimension: Dimension): Dimension[];
|
||||
layout(width: number, height: number): void;
|
||||
layout(dim1: Dimension | number, dim2?: number): Dimension[] | void {
|
||||
const sizes = super.layout(dim1 instanceof Dimension ? dim1 : new Dimension(dim1, dim2));
|
||||
layout(width: number, height: number): void {
|
||||
|
||||
this.doLayout(sizes[1]);
|
||||
// Layout contents
|
||||
const contentAreaSize = super.layoutContents(width, height).contentSize;
|
||||
|
||||
if (dim1 instanceof Dimension) {
|
||||
return sizes;
|
||||
}
|
||||
// Layout editor container
|
||||
this.doLayout(contentAreaSize);
|
||||
}
|
||||
|
||||
private doLayout(dimension: Dimension): void {
|
||||
this.dimension = dimension;
|
||||
this._dimension = dimension;
|
||||
|
||||
// Layout Grid
|
||||
this.centeredLayoutWidget.layout(this.dimension.width, this.dimension.height);
|
||||
this.centeredLayoutWidget.layout(this._dimension.width, this._dimension.height);
|
||||
|
||||
// Event
|
||||
this._onDidLayout.fire(dimension);
|
||||
@@ -1039,3 +1030,5 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
registerSingleton(IEditorGroupsService, EditorPart);
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
import 'vs/css!./media/editorpicker';
|
||||
import * as nls from 'vs/nls';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IIconLabelValueOptions } from 'vs/base/browser/ui/iconLabel/iconLabel';
|
||||
import { IAutoFocus, Mode, IEntryRunContext, IQuickNavigateConfiguration, IModel } from 'vs/base/parts/quickopen/common/quickOpen';
|
||||
import { QuickOpenModel, QuickOpenEntry, QuickOpenEntryGroup, QuickOpenItemAccessor } from 'vs/base/parts/quickopen/browser/quickOpenModel';
|
||||
@@ -14,7 +13,7 @@ import { getIconClasses } from 'vs/editor/common/services/getIconClasses';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { QuickOpenHandler } from 'vs/workbench/browser/quickopen';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IEditorGroupsService, IEditorGroup, EditorsOrder, GroupsOrder } from 'vs/workbench/services/group/common/editorGroupsService';
|
||||
import { IEditorGroupsService, IEditorGroup, EditorsOrder, GroupsOrder } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { EditorInput, toResource } from 'vs/workbench/common/editor';
|
||||
import { compareItemsByScore, scoreItem, ScorerCache, prepareQuery } from 'vs/base/parts/quickopen/common/quickOpenScorer';
|
||||
@@ -33,12 +32,12 @@ export class EditorPickerEntry extends QuickOpenEntryGroup {
|
||||
|
||||
getLabelOptions(): IIconLabelValueOptions {
|
||||
return {
|
||||
extraClasses: getIconClasses(this.modelService, this.modeService, this.getResource()),
|
||||
extraClasses: getIconClasses(this.modelService, this.modeService, this.getResource() || undefined),
|
||||
italic: !this._group.isPinned(this.editor)
|
||||
};
|
||||
}
|
||||
|
||||
getLabel(): string {
|
||||
getLabel() {
|
||||
return this.editor.getName();
|
||||
}
|
||||
|
||||
@@ -50,7 +49,7 @@ export class EditorPickerEntry extends QuickOpenEntryGroup {
|
||||
return this._group;
|
||||
}
|
||||
|
||||
getResource(): URI {
|
||||
getResource() {
|
||||
return toResource(this.editor, { supportSideBySide: true });
|
||||
}
|
||||
|
||||
@@ -58,7 +57,7 @@ export class EditorPickerEntry extends QuickOpenEntryGroup {
|
||||
return nls.localize('entryAriaLabel', "{0}, editor group picker", this.getLabel());
|
||||
}
|
||||
|
||||
getDescription(): string {
|
||||
getDescription() {
|
||||
return this.editor.getDescription();
|
||||
}
|
||||
|
||||
@@ -109,7 +108,7 @@ export abstract class BaseEditorPicker extends QuickOpenHandler {
|
||||
return false;
|
||||
}
|
||||
|
||||
e.setHighlights(itemScore.labelMatch, itemScore.descriptionMatch);
|
||||
e.setHighlights(itemScore.labelMatch || [], itemScore.descriptionMatch);
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
@@ -7,16 +7,15 @@ import 'vs/css!./media/editorstatus';
|
||||
import * as nls from 'vs/nls';
|
||||
import { $, append, runAtThisOrScheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import * as paths from 'vs/base/common/paths';
|
||||
import { extname, basename } from 'vs/base/common/resources';
|
||||
import * as types from 'vs/base/common/types';
|
||||
import { URI as uri } from 'vs/base/common/uri';
|
||||
import { IStatusbarItem } from 'vs/workbench/browser/parts/statusbar/statusbar';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { language, LANGUAGE_DEFAULT, AccessibilitySupport } from 'vs/base/common/platform';
|
||||
import * as browser from 'vs/base/browser/browser';
|
||||
import { Language } from 'vs/base/common/platform';
|
||||
import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorInput';
|
||||
import { IFileEditorInput, EncodingMode, IEncodingSupport, toResource, SideBySideEditorInput, IEditor as IBaseEditor, IEditorInput } from 'vs/workbench/common/editor';
|
||||
import { IDisposable, combinedDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, combinedDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
|
||||
import { IEditorAction } from 'vs/editor/common/editorCommon';
|
||||
import { EndOfLineSequence, ITextModel } from 'vs/editor/common/model';
|
||||
@@ -27,7 +26,6 @@ import { BaseBinaryResourceEditor } from 'vs/workbench/browser/parts/editor/bina
|
||||
import { BinaryResourceDiffEditor } from 'vs/workbench/browser/parts/editor/binaryDiffEditor';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
|
||||
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { SUPPORTED_ENCODINGS, IFileService, FILES_ASSOCIATIONS_CONFIG } from 'vs/platform/files/common/files';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IModeService, ILanguageSelection } from 'vs/editor/common/services/modeService';
|
||||
@@ -41,7 +39,7 @@ import { ITextFileService } from 'vs/workbench/services/textfile/common/textfile
|
||||
import { ICursorPositionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
|
||||
import { IConfigurationChangedEvent, IEditorOptions } from 'vs/editor/common/config/editorOptions';
|
||||
import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration';
|
||||
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { deepClone } from 'vs/base/common/objects';
|
||||
import { ICodeEditor, isCodeEditor, isDiffEditor, getCodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
@@ -51,6 +49,10 @@ import { getIconClasses } from 'vs/editor/common/services/getIconClasses';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { INotificationHandle, INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IAccessibilityService, AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility';
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
import { QueryEditorService } from 'sql/workbench/services/queryEditor/browser/queryEditorService';
|
||||
|
||||
class SideBySideEditorEncodingSupport implements IEncodingSupport {
|
||||
constructor(private master: IEncodingSupport, private details: IEncodingSupport) { }
|
||||
@@ -64,10 +66,7 @@ class SideBySideEditorEncodingSupport implements IEncodingSupport {
|
||||
}
|
||||
}
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
import { QueryEditorService } from 'sql/workbench/services/queryEditor/browser/queryEditorService';
|
||||
|
||||
function toEditorWithEncodingSupport(input: IEditorInput): IEncodingSupport {
|
||||
function toEditorWithEncodingSupport(input: IEditorInput): IEncodingSupport | null {
|
||||
|
||||
// Untitled Editor
|
||||
if (input instanceof UntitledEditorInput) {
|
||||
@@ -104,25 +103,14 @@ interface IEditorSelectionStatus {
|
||||
class StateChange {
|
||||
_stateChangeBrand: void;
|
||||
|
||||
indentation: boolean;
|
||||
selectionStatus: boolean;
|
||||
mode: boolean;
|
||||
encoding: boolean;
|
||||
EOL: boolean;
|
||||
tabFocusMode: boolean;
|
||||
screenReaderMode: boolean;
|
||||
metadata: boolean;
|
||||
|
||||
constructor() {
|
||||
this.indentation = false;
|
||||
this.selectionStatus = false;
|
||||
this.mode = false;
|
||||
this.encoding = false;
|
||||
this.EOL = false;
|
||||
this.tabFocusMode = false;
|
||||
this.screenReaderMode = false;
|
||||
this.metadata = false;
|
||||
}
|
||||
indentation: boolean = false;
|
||||
selectionStatus: boolean = false;
|
||||
mode: boolean = false;
|
||||
encoding: boolean = false;
|
||||
EOL: boolean = false;
|
||||
tabFocusMode: boolean = false;
|
||||
screenReaderMode: boolean = false;
|
||||
metadata: boolean = false;
|
||||
|
||||
combine(other: StateChange) {
|
||||
this.indentation = this.indentation || other.indentation;
|
||||
@@ -134,6 +122,17 @@ class StateChange {
|
||||
this.screenReaderMode = this.screenReaderMode || other.screenReaderMode;
|
||||
this.metadata = this.metadata || other.metadata;
|
||||
}
|
||||
|
||||
public hasChanges(): boolean {
|
||||
return this.indentation
|
||||
|| this.selectionStatus
|
||||
|| this.mode
|
||||
|| this.encoding
|
||||
|| this.EOL
|
||||
|| this.tabFocusMode
|
||||
|| this.screenReaderMode
|
||||
|| this.metadata;
|
||||
}
|
||||
}
|
||||
|
||||
interface StateDelta {
|
||||
@@ -144,33 +143,33 @@ interface StateDelta {
|
||||
indentation?: string;
|
||||
tabFocusMode?: boolean;
|
||||
screenReaderMode?: boolean;
|
||||
metadata?: string;
|
||||
metadata?: string | null;
|
||||
}
|
||||
|
||||
class State {
|
||||
private _selectionStatus: string;
|
||||
get selectionStatus(): string { return this._selectionStatus; }
|
||||
private _selectionStatus: string | null | undefined;
|
||||
get selectionStatus(): string | null | undefined { return this._selectionStatus; }
|
||||
|
||||
private _mode: string;
|
||||
get mode(): string { return this._mode; }
|
||||
private _mode: string | null | undefined;
|
||||
get mode(): string | null | undefined { return this._mode; }
|
||||
|
||||
private _encoding: string;
|
||||
get encoding(): string { return this._encoding; }
|
||||
private _encoding: string | null | undefined;
|
||||
get encoding(): string | null | undefined { return this._encoding; }
|
||||
|
||||
private _EOL: string;
|
||||
get EOL(): string { return this._EOL; }
|
||||
private _EOL: string | null | undefined;
|
||||
get EOL(): string | null | undefined { return this._EOL; }
|
||||
|
||||
private _indentation: string;
|
||||
get indentation(): string { return this._indentation; }
|
||||
private _indentation: string | null | undefined;
|
||||
get indentation(): string | null | undefined { return this._indentation; }
|
||||
|
||||
private _tabFocusMode: boolean;
|
||||
get tabFocusMode(): boolean { return this._tabFocusMode; }
|
||||
private _tabFocusMode: boolean | null | undefined;
|
||||
get tabFocusMode(): boolean | null | undefined { return this._tabFocusMode; }
|
||||
|
||||
private _screenReaderMode: boolean;
|
||||
get screenReaderMode(): boolean { return this._screenReaderMode; }
|
||||
private _screenReaderMode: boolean | null | undefined;
|
||||
get screenReaderMode(): boolean | null | undefined { return this._screenReaderMode; }
|
||||
|
||||
private _metadata: string;
|
||||
get metadata(): string { return this._metadata; }
|
||||
private _metadata: string | null | undefined;
|
||||
get metadata(): string | null | undefined { return this._metadata; }
|
||||
|
||||
constructor() {
|
||||
this._selectionStatus = null;
|
||||
@@ -183,70 +182,58 @@ class State {
|
||||
}
|
||||
|
||||
update(update: StateDelta): StateChange {
|
||||
const e = new StateChange();
|
||||
let somethingChanged = false;
|
||||
const change = new StateChange();
|
||||
|
||||
if (typeof update.selectionStatus !== 'undefined') {
|
||||
if ('selectionStatus' in update) {
|
||||
if (this._selectionStatus !== update.selectionStatus) {
|
||||
this._selectionStatus = update.selectionStatus;
|
||||
somethingChanged = true;
|
||||
e.selectionStatus = true;
|
||||
change.selectionStatus = true;
|
||||
}
|
||||
}
|
||||
if (typeof update.indentation !== 'undefined') {
|
||||
if ('indentation' in update) {
|
||||
if (this._indentation !== update.indentation) {
|
||||
this._indentation = update.indentation;
|
||||
somethingChanged = true;
|
||||
e.indentation = true;
|
||||
change.indentation = true;
|
||||
}
|
||||
}
|
||||
if (typeof update.mode !== 'undefined') {
|
||||
if ('mode' in update) {
|
||||
if (this._mode !== update.mode) {
|
||||
this._mode = update.mode;
|
||||
somethingChanged = true;
|
||||
e.mode = true;
|
||||
change.mode = true;
|
||||
}
|
||||
}
|
||||
if (typeof update.encoding !== 'undefined') {
|
||||
if ('encoding' in update) {
|
||||
if (this._encoding !== update.encoding) {
|
||||
this._encoding = update.encoding;
|
||||
somethingChanged = true;
|
||||
e.encoding = true;
|
||||
change.encoding = true;
|
||||
}
|
||||
}
|
||||
if (typeof update.EOL !== 'undefined') {
|
||||
if ('EOL' in update) {
|
||||
if (this._EOL !== update.EOL) {
|
||||
this._EOL = update.EOL;
|
||||
somethingChanged = true;
|
||||
e.EOL = true;
|
||||
change.EOL = true;
|
||||
}
|
||||
}
|
||||
if (typeof update.tabFocusMode !== 'undefined') {
|
||||
if ('tabFocusMode' in update) {
|
||||
if (this._tabFocusMode !== update.tabFocusMode) {
|
||||
this._tabFocusMode = update.tabFocusMode;
|
||||
somethingChanged = true;
|
||||
e.tabFocusMode = true;
|
||||
change.tabFocusMode = true;
|
||||
}
|
||||
}
|
||||
if (typeof update.screenReaderMode !== 'undefined') {
|
||||
if ('screenReaderMode' in update) {
|
||||
if (this._screenReaderMode !== update.screenReaderMode) {
|
||||
this._screenReaderMode = update.screenReaderMode;
|
||||
somethingChanged = true;
|
||||
e.screenReaderMode = true;
|
||||
change.screenReaderMode = true;
|
||||
}
|
||||
}
|
||||
if (typeof update.metadata !== 'undefined') {
|
||||
if ('metadata' in update) {
|
||||
if (this._metadata !== update.metadata) {
|
||||
this._metadata = update.metadata;
|
||||
somethingChanged = true;
|
||||
e.metadata = true;
|
||||
change.metadata = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (somethingChanged) {
|
||||
return e;
|
||||
}
|
||||
return null;
|
||||
return change;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,34 +247,51 @@ const nlsTabFocusMode = nls.localize('tabFocusModeEnabled', "Tab Moves Focus");
|
||||
const nlsScreenReaderDetected = nls.localize('screenReaderDetected', "Screen Reader Optimized");
|
||||
const nlsScreenReaderDetectedTitle = nls.localize('screenReaderDetectedExtra', "If you are not using a Screen Reader, please change the setting `editor.accessibilitySupport` to \"off\".");
|
||||
|
||||
function setDisplay(el: HTMLElement, desiredValue: string): void {
|
||||
if (el.style.display !== desiredValue) {
|
||||
el.style.display = desiredValue;
|
||||
|
||||
class StatusBarItem {
|
||||
private _showing = true;
|
||||
|
||||
constructor(
|
||||
private readonly element: HTMLElement,
|
||||
title: string,
|
||||
) {
|
||||
this.setVisible(false);
|
||||
this.element.title = title;
|
||||
}
|
||||
|
||||
public set textContent(value: string) {
|
||||
this.element.textContent = value;
|
||||
}
|
||||
|
||||
public set onclick(value: () => void) {
|
||||
this.element.onclick = value;
|
||||
}
|
||||
|
||||
public setVisible(shouldShow: boolean): void {
|
||||
if (shouldShow !== this._showing) {
|
||||
this._showing = shouldShow;
|
||||
this.element.style.display = shouldShow ? '' : 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
function show(el: HTMLElement): void {
|
||||
setDisplay(el, '');
|
||||
}
|
||||
function hide(el: HTMLElement): void {
|
||||
setDisplay(el, 'none');
|
||||
}
|
||||
|
||||
|
||||
export class EditorStatus implements IStatusbarItem {
|
||||
private state: State;
|
||||
private element: HTMLElement;
|
||||
private tabFocusModeElement: HTMLElement;
|
||||
private screenRedearModeElement: HTMLElement;
|
||||
private indentationElement: HTMLElement;
|
||||
private selectionElement: HTMLElement;
|
||||
private encodingElement: HTMLElement;
|
||||
private eolElement: HTMLElement;
|
||||
private modeElement: HTMLElement;
|
||||
private metadataElement: HTMLElement;
|
||||
private tabFocusModeElement: StatusBarItem;
|
||||
private screenRedearModeElement: StatusBarItem;
|
||||
private indentationElement: StatusBarItem;
|
||||
private selectionElement: StatusBarItem;
|
||||
private encodingElement: StatusBarItem;
|
||||
private eolElement: StatusBarItem;
|
||||
private modeElement: StatusBarItem;
|
||||
private metadataElement: StatusBarItem;
|
||||
private toDispose: IDisposable[];
|
||||
private activeEditorListeners: IDisposable[];
|
||||
private delayedRender: IDisposable;
|
||||
private toRender: StateChange;
|
||||
private screenReaderNotification: INotificationHandle;
|
||||
private delayedRender: IDisposable | null;
|
||||
private toRender: StateChange | null;
|
||||
private screenReaderNotification: INotificationHandle | null;
|
||||
|
||||
constructor(
|
||||
@IEditorService private readonly editorService: IEditorService,
|
||||
@@ -296,8 +300,9 @@ export class EditorStatus implements IStatusbarItem {
|
||||
@IUntitledEditorService private readonly untitledEditorService: IUntitledEditorService,
|
||||
@IModeService private readonly modeService: IModeService,
|
||||
@ITextFileService private readonly textFileService: ITextFileService,
|
||||
@IWorkspaceConfigurationService private readonly configurationService: IWorkspaceConfigurationService,
|
||||
@INotificationService private readonly notificationService: INotificationService
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IAccessibilityService private readonly accessibilityService: IAccessibilityService
|
||||
) {
|
||||
this.toDispose = [];
|
||||
this.activeEditorListeners = [];
|
||||
@@ -307,59 +312,57 @@ export class EditorStatus implements IStatusbarItem {
|
||||
render(container: HTMLElement): IDisposable {
|
||||
this.element = append(container, $('.editor-statusbar-item'));
|
||||
|
||||
this.tabFocusModeElement = append(this.element, $('a.editor-status-tabfocusmode.status-bar-info'));
|
||||
this.tabFocusModeElement.title = nls.localize('disableTabMode', "Disable Accessibility Mode");
|
||||
this.tabFocusModeElement = new StatusBarItem(
|
||||
append(this.element, $('a.editor-status-tabfocusmode.status-bar-info')),
|
||||
nls.localize('disableTabMode', "Disable Accessibility Mode"));
|
||||
this.tabFocusModeElement.onclick = () => this.onTabFocusModeClick();
|
||||
this.tabFocusModeElement.textContent = nlsTabFocusMode;
|
||||
hide(this.tabFocusModeElement);
|
||||
|
||||
this.screenRedearModeElement = append(this.element, $('a.editor-status-screenreadermode.status-bar-info'));
|
||||
this.screenRedearModeElement = new StatusBarItem(
|
||||
append(this.element, $('a.editor-status-screenreadermode.status-bar-info')),
|
||||
nlsScreenReaderDetectedTitle);
|
||||
this.screenRedearModeElement.textContent = nlsScreenReaderDetected;
|
||||
this.screenRedearModeElement.title = nlsScreenReaderDetectedTitle;
|
||||
this.screenRedearModeElement.onclick = () => this.onScreenReaderModeClick();
|
||||
hide(this.screenRedearModeElement);
|
||||
|
||||
this.selectionElement = append(this.element, $('a.editor-status-selection'));
|
||||
this.selectionElement.title = nls.localize('gotoLine', "Go to Line");
|
||||
this.selectionElement = new StatusBarItem(
|
||||
append(this.element, $('a.editor-status-selection')),
|
||||
nls.localize('gotoLine', "Go to Line"));
|
||||
this.selectionElement.onclick = () => this.onSelectionClick();
|
||||
hide(this.selectionElement);
|
||||
|
||||
this.indentationElement = append(this.element, $('a.editor-status-indentation'));
|
||||
this.indentationElement.title = nls.localize('selectIndentation', "Select Indentation");
|
||||
this.indentationElement = new StatusBarItem(
|
||||
append(this.element, $('a.editor-status-indentation')),
|
||||
nls.localize('selectIndentation', "Select Indentation"));
|
||||
this.indentationElement.onclick = () => this.onIndentationClick();
|
||||
hide(this.indentationElement);
|
||||
|
||||
this.encodingElement = append(this.element, $('a.editor-status-encoding'));
|
||||
this.encodingElement.title = nls.localize('selectEncoding', "Select Encoding");
|
||||
this.encodingElement = new StatusBarItem(
|
||||
append(this.element, $('a.editor-status-encoding')),
|
||||
nls.localize('selectEncoding', "Select Encoding"));
|
||||
this.encodingElement.onclick = () => this.onEncodingClick();
|
||||
hide(this.encodingElement);
|
||||
|
||||
this.eolElement = append(this.element, $('a.editor-status-eol'));
|
||||
this.eolElement.title = nls.localize('selectEOL', "Select End of Line Sequence");
|
||||
this.eolElement = new StatusBarItem(
|
||||
append(this.element, $('a.editor-status-eol')),
|
||||
nls.localize('selectEOL', "Select End of Line Sequence"));
|
||||
this.eolElement.onclick = () => this.onEOLClick();
|
||||
hide(this.eolElement);
|
||||
|
||||
this.modeElement = append(this.element, $('a.editor-status-mode'));
|
||||
this.modeElement.title = nls.localize('selectLanguageMode', "Select Language Mode");
|
||||
this.modeElement = new StatusBarItem(
|
||||
append(this.element, $('a.editor-status-mode')),
|
||||
nls.localize('selectLanguageMode', "Select Language Mode"));
|
||||
this.modeElement.onclick = () => this.onModeClick();
|
||||
hide(this.modeElement);
|
||||
|
||||
this.metadataElement = append(this.element, $('span.editor-status-metadata'));
|
||||
this.metadataElement.title = nls.localize('fileInfo', "File Information");
|
||||
hide(this.metadataElement);
|
||||
this.metadataElement = new StatusBarItem(
|
||||
append(this.element, $('span.editor-status-metadata')),
|
||||
nls.localize('fileInfo', "File Information"));
|
||||
|
||||
this.delayedRender = null;
|
||||
this.toRender = null;
|
||||
|
||||
this.toDispose.push(
|
||||
{
|
||||
dispose: () => {
|
||||
if (this.delayedRender) {
|
||||
this.delayedRender.dispose();
|
||||
this.delayedRender = null;
|
||||
}
|
||||
toDisposable(() => {
|
||||
if (this.delayedRender) {
|
||||
this.delayedRender.dispose();
|
||||
this.delayedRender = null;
|
||||
}
|
||||
},
|
||||
}),
|
||||
this.editorService.onDidActiveEditorChange(() => this.updateStatusBar()),
|
||||
this.untitledEditorService.onDidChangeEncoding(r => this.onResourceEncodingChange(r)),
|
||||
this.textFileService.models.onModelEncodingChanged(e => this.onResourceEncodingChange(e.resource)),
|
||||
@@ -371,7 +374,7 @@ export class EditorStatus implements IStatusbarItem {
|
||||
|
||||
private updateState(update: StateDelta): void {
|
||||
const changed = this.state.update(update);
|
||||
if (!changed) {
|
||||
if (!changed.hasChanges()) {
|
||||
// Nothing really changed
|
||||
return;
|
||||
}
|
||||
@@ -382,7 +385,9 @@ export class EditorStatus implements IStatusbarItem {
|
||||
this.delayedRender = null;
|
||||
const toRender = this.toRender;
|
||||
this.toRender = null;
|
||||
this._renderNow(toRender);
|
||||
if (toRender) {
|
||||
this._renderNow(toRender);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.toRender.combine(changed);
|
||||
@@ -391,79 +396,71 @@ export class EditorStatus implements IStatusbarItem {
|
||||
|
||||
private _renderNow(changed: StateChange): void {
|
||||
if (changed.tabFocusMode) {
|
||||
if (this.state.tabFocusMode && this.state.tabFocusMode === true) {
|
||||
show(this.tabFocusModeElement);
|
||||
} else {
|
||||
hide(this.tabFocusModeElement);
|
||||
}
|
||||
this.tabFocusModeElement.setVisible(!!this.state.tabFocusMode);
|
||||
}
|
||||
|
||||
if (changed.screenReaderMode) {
|
||||
if (this.state.screenReaderMode && this.state.screenReaderMode === true) {
|
||||
show(this.screenRedearModeElement);
|
||||
} else {
|
||||
hide(this.screenRedearModeElement);
|
||||
}
|
||||
this.screenRedearModeElement.setVisible(!!this.state.screenReaderMode);
|
||||
}
|
||||
|
||||
if (changed.indentation) {
|
||||
if (this.state.indentation) {
|
||||
this.indentationElement.textContent = this.state.indentation;
|
||||
show(this.indentationElement);
|
||||
this.indentationElement.setVisible(true);
|
||||
} else {
|
||||
hide(this.indentationElement);
|
||||
this.indentationElement.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (changed.selectionStatus) {
|
||||
if (this.state.selectionStatus && !this.state.screenReaderMode) {
|
||||
this.selectionElement.textContent = this.state.selectionStatus;
|
||||
show(this.selectionElement);
|
||||
this.selectionElement.setVisible(true);
|
||||
} else {
|
||||
hide(this.selectionElement);
|
||||
this.selectionElement.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (changed.encoding) {
|
||||
if (this.state.encoding) {
|
||||
this.encodingElement.textContent = this.state.encoding;
|
||||
show(this.encodingElement);
|
||||
this.encodingElement.setVisible(true);
|
||||
} else {
|
||||
hide(this.encodingElement);
|
||||
this.encodingElement.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (changed.EOL) {
|
||||
if (this.state.EOL) {
|
||||
this.eolElement.textContent = this.state.EOL === '\r\n' ? nlsEOLCRLF : nlsEOLLF;
|
||||
show(this.eolElement);
|
||||
this.eolElement.setVisible(true);
|
||||
} else {
|
||||
hide(this.eolElement);
|
||||
this.eolElement.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (changed.mode) {
|
||||
if (this.state.mode) {
|
||||
this.modeElement.textContent = this.state.mode;
|
||||
show(this.modeElement);
|
||||
this.modeElement.setVisible(true);
|
||||
} else {
|
||||
hide(this.modeElement);
|
||||
this.modeElement.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (changed.metadata) {
|
||||
if (this.state.metadata) {
|
||||
this.metadataElement.textContent = this.state.metadata;
|
||||
show(this.metadataElement);
|
||||
this.metadataElement.setVisible(true);
|
||||
} else {
|
||||
hide(this.metadataElement);
|
||||
this.metadataElement.setVisible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private getSelectionLabel(info: IEditorSelectionStatus): string {
|
||||
private getSelectionLabel(info: IEditorSelectionStatus): string | undefined {
|
||||
if (!info || !info.selections) {
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (info.selections.length === 1) {
|
||||
@@ -482,7 +479,7 @@ export class EditorStatus implements IStatusbarItem {
|
||||
return strings.format(nlsMultiSelection, info.selections.length);
|
||||
}
|
||||
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private onModeClick(): void {
|
||||
@@ -502,8 +499,7 @@ export class EditorStatus implements IStatusbarItem {
|
||||
if (!this.screenReaderNotification) {
|
||||
this.screenReaderNotification = this.notificationService.prompt(
|
||||
Severity.Info,
|
||||
// {{SQL CARBON EDIT}}
|
||||
nls.localize('screenReaderDetectedExplanation.question', "Are you using a screen reader to operate Azure Data Studio?"),
|
||||
nls.localize('screenReaderDetectedExplanation.question', "Are you using a screen reader to operate Azure Data Studio? (Certain features like folding, minimap or word wrap are disabled when using a screen reader)"),
|
||||
[{
|
||||
label: nls.localize('screenReaderDetectedExplanation.answerYes', "Yes"),
|
||||
run: () => {
|
||||
@@ -548,7 +544,7 @@ export class EditorStatus implements IStatusbarItem {
|
||||
|
||||
private updateStatusBar(): void {
|
||||
const activeControl = this.editorService.activeControl;
|
||||
const activeCodeEditor = activeControl ? getCodeEditor(activeControl.getControl()) : undefined;
|
||||
const activeCodeEditor = activeControl ? types.withNullAsUndefined(getCodeEditor(activeControl.getControl())) : undefined;
|
||||
|
||||
// Update all states
|
||||
this.onScreenReaderModeChange(activeCodeEditor);
|
||||
@@ -586,11 +582,13 @@ export class EditorStatus implements IStatusbarItem {
|
||||
this.activeEditorListeners.push(activeCodeEditor.onDidChangeModelContent((e) => {
|
||||
this.onEOLChange(activeCodeEditor);
|
||||
|
||||
let selections = activeCodeEditor.getSelections();
|
||||
for (const change of e.changes) {
|
||||
if (selections.some(selection => Range.areIntersecting(selection, change.range))) {
|
||||
this.onSelectionChange(activeCodeEditor);
|
||||
break;
|
||||
const selections = activeCodeEditor.getSelections();
|
||||
if (selections) {
|
||||
for (const change of e.changes) {
|
||||
if (selections.some(selection => Range.areIntersecting(selection, change.range))) {
|
||||
this.onSelectionChange(activeCodeEditor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
@@ -630,8 +628,8 @@ export class EditorStatus implements IStatusbarItem {
|
||||
}
|
||||
}
|
||||
|
||||
private onModeChange(editorWidget: ICodeEditor): void {
|
||||
let info: StateDelta = { mode: null };
|
||||
private onModeChange(editorWidget: ICodeEditor | undefined): void {
|
||||
let info: StateDelta = { mode: undefined };
|
||||
|
||||
// We only support text based editors
|
||||
if (editorWidget) {
|
||||
@@ -639,15 +637,15 @@ export class EditorStatus implements IStatusbarItem {
|
||||
if (textModel) {
|
||||
// Compute mode
|
||||
const modeId = textModel.getLanguageIdentifier().language;
|
||||
info = { mode: this.modeService.getLanguageName(modeId) };
|
||||
info = { mode: this.modeService.getLanguageName(modeId) || undefined };
|
||||
}
|
||||
}
|
||||
|
||||
this.updateState(info);
|
||||
}
|
||||
|
||||
private onIndentationChange(editorWidget: ICodeEditor): void {
|
||||
const update: StateDelta = { indentation: null };
|
||||
private onIndentationChange(editorWidget: ICodeEditor | undefined): void {
|
||||
const update: StateDelta = { indentation: undefined };
|
||||
|
||||
if (editorWidget) {
|
||||
const model = editorWidget.getModel();
|
||||
@@ -655,7 +653,7 @@ export class EditorStatus implements IStatusbarItem {
|
||||
const modelOpts = model.getOptions();
|
||||
update.indentation = (
|
||||
modelOpts.insertSpaces
|
||||
? nls.localize('spacesSize', "Spaces: {0}", modelOpts.tabSize)
|
||||
? nls.localize('spacesSize', "Spaces: {0}", modelOpts.indentSize)
|
||||
: nls.localize({ key: 'tabSize', comment: ['Tab corresponds to the tab key'] }, "Tab Size: {0}", modelOpts.tabSize)
|
||||
);
|
||||
}
|
||||
@@ -664,8 +662,8 @@ export class EditorStatus implements IStatusbarItem {
|
||||
this.updateState(update);
|
||||
}
|
||||
|
||||
private onMetadataChange(editor: IBaseEditor): void {
|
||||
const update: StateDelta = { metadata: null };
|
||||
private onMetadataChange(editor: IBaseEditor | undefined): void {
|
||||
const update: StateDelta = { metadata: undefined };
|
||||
|
||||
if (editor instanceof BaseBinaryResourceEditor || editor instanceof BinaryResourceDiffEditor) {
|
||||
update.metadata = editor.getMetadata();
|
||||
@@ -676,12 +674,12 @@ export class EditorStatus implements IStatusbarItem {
|
||||
|
||||
private _promptedScreenReader: boolean = false;
|
||||
|
||||
private onScreenReaderModeChange(editorWidget: ICodeEditor): void {
|
||||
private onScreenReaderModeChange(editorWidget: ICodeEditor | undefined): void {
|
||||
let screenReaderMode = false;
|
||||
|
||||
// We only support text based editors
|
||||
if (editorWidget) {
|
||||
const screenReaderDetected = (browser.getAccessibilitySupport() === AccessibilitySupport.Enabled);
|
||||
const screenReaderDetected = (this.accessibilityService.getAccessibilitySupport() === AccessibilitySupport.Enabled);
|
||||
if (screenReaderDetected) {
|
||||
const screenReaderConfiguration = this.configurationService.getValue<IEditorOptions>('editor').accessibilitySupport;
|
||||
if (screenReaderConfiguration === 'auto') {
|
||||
@@ -705,7 +703,7 @@ export class EditorStatus implements IStatusbarItem {
|
||||
this.updateState({ screenReaderMode: screenReaderMode });
|
||||
}
|
||||
|
||||
private onSelectionChange(editorWidget: ICodeEditor): void {
|
||||
private onSelectionChange(editorWidget: ICodeEditor | undefined): void {
|
||||
const info: IEditorSelectionStatus = {};
|
||||
|
||||
// We only support text based editors
|
||||
@@ -719,13 +717,13 @@ export class EditorStatus implements IStatusbarItem {
|
||||
const textModel = editorWidget.getModel();
|
||||
if (textModel) {
|
||||
info.selections.forEach(selection => {
|
||||
info.charactersSelected += textModel.getValueLengthInRange(selection);
|
||||
info.charactersSelected! += textModel.getValueLengthInRange(selection);
|
||||
});
|
||||
}
|
||||
|
||||
// Compute the visible column for one selection. This will properly handle tabs and their configured widths
|
||||
if (info.selections.length === 1) {
|
||||
const visibleColumn = editorWidget.getVisibleColumnFromPosition(editorWidget.getPosition());
|
||||
const visibleColumn = editorWidget.getVisibleColumnFromPosition(editorWidget.getPosition()!);
|
||||
|
||||
let selectionClone = info.selections[0].clone(); // do not modify the original position we got from the editor
|
||||
selectionClone = new Selection(
|
||||
@@ -742,8 +740,8 @@ export class EditorStatus implements IStatusbarItem {
|
||||
this.updateState({ selectionStatus: this.getSelectionLabel(info) });
|
||||
}
|
||||
|
||||
private onEOLChange(editorWidget: ICodeEditor): void {
|
||||
const info: StateDelta = { EOL: null };
|
||||
private onEOLChange(editorWidget: ICodeEditor | undefined): void {
|
||||
const info: StateDelta = { EOL: undefined };
|
||||
|
||||
if (editorWidget && !editorWidget.getConfiguration().readOnly) {
|
||||
const codeEditorModel = editorWidget.getModel();
|
||||
@@ -760,11 +758,11 @@ export class EditorStatus implements IStatusbarItem {
|
||||
return;
|
||||
}
|
||||
|
||||
const info: StateDelta = { encoding: null };
|
||||
const info: StateDelta = { encoding: undefined };
|
||||
|
||||
// We only support text based editors
|
||||
if (e && (isCodeEditor(e.getControl()) || isDiffEditor(e.getControl()))) {
|
||||
const encodingSupport: IEncodingSupport = toEditorWithEncodingSupport(e.input);
|
||||
const encodingSupport: IEncodingSupport | null = e.input ? toEditorWithEncodingSupport(e.input) : null;
|
||||
if (encodingSupport) {
|
||||
const rawEncoding = encodingSupport.getEncoding();
|
||||
const encodingInfo = SUPPORTED_ENCODINGS[rawEncoding];
|
||||
@@ -798,11 +796,11 @@ export class EditorStatus implements IStatusbarItem {
|
||||
private isActiveEditor(control: IBaseEditor): boolean {
|
||||
const activeControl = this.editorService.activeControl;
|
||||
|
||||
return activeControl && activeControl === control;
|
||||
return !!activeControl && activeControl === control;
|
||||
}
|
||||
}
|
||||
|
||||
function isWritableCodeEditor(codeEditor: ICodeEditor): boolean {
|
||||
function isWritableCodeEditor(codeEditor: ICodeEditor | undefined): boolean {
|
||||
if (!codeEditor) {
|
||||
return false;
|
||||
}
|
||||
@@ -811,7 +809,7 @@ function isWritableCodeEditor(codeEditor: ICodeEditor): boolean {
|
||||
}
|
||||
|
||||
function isWritableBaseEditor(e: IBaseEditor): boolean {
|
||||
return e && isWritableCodeEditor(getCodeEditor(e.getControl()));
|
||||
return e && isWritableCodeEditor(getCodeEditor(e.getControl()) || undefined);
|
||||
}
|
||||
|
||||
export class ShowLanguageExtensionsAction extends Action {
|
||||
@@ -844,7 +842,7 @@ export class ChangeModeAction extends Action {
|
||||
@IModeService private readonly modeService: IModeService,
|
||||
@IModelService private readonly modelService: IModelService,
|
||||
@IEditorService private readonly editorService: IEditorService,
|
||||
@IWorkspaceConfigurationService private readonly configurationService: IWorkspaceConfigurationService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService,
|
||||
@IPreferencesService private readonly preferencesService: IPreferencesService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@@ -860,19 +858,19 @@ export class ChangeModeAction extends Action {
|
||||
}
|
||||
|
||||
const textModel = activeTextEditorWidget.getModel();
|
||||
const resource = toResource(this.editorService.activeEditor, { supportSideBySide: true });
|
||||
const resource = this.editorService.activeEditor ? toResource(this.editorService.activeEditor, { supportSideBySide: true }) : null;
|
||||
|
||||
let hasLanguageSupport = !!resource;
|
||||
if (resource.scheme === Schemas.untitled && !this.untitledEditorService.hasAssociatedFilePath(resource)) {
|
||||
if (resource && resource.scheme === Schemas.untitled && !this.untitledEditorService.hasAssociatedFilePath(resource)) {
|
||||
hasLanguageSupport = false; // no configuration for untitled resources (e.g. "Untitled-1")
|
||||
}
|
||||
|
||||
// Compute mode
|
||||
let currentModeId: string;
|
||||
let currentModeId: string | undefined;
|
||||
let modeId: string;
|
||||
if (textModel) {
|
||||
modeId = textModel.getLanguageIdentifier().language;
|
||||
currentModeId = this.modeService.getLanguageName(modeId);
|
||||
currentModeId = this.modeService.getLanguageName(modeId) || undefined;
|
||||
}
|
||||
|
||||
// All languages are valid picks
|
||||
@@ -886,7 +884,7 @@ export class ChangeModeAction extends Action {
|
||||
}
|
||||
|
||||
// construct a fake resource to be able to show nice icons if any
|
||||
let fakeResource: uri;
|
||||
let fakeResource: uri | undefined;
|
||||
const extensions = this.modeService.getExtensions(lang);
|
||||
if (extensions && extensions.length) {
|
||||
fakeResource = uri.file(extensions[0]);
|
||||
@@ -912,8 +910,8 @@ export class ChangeModeAction extends Action {
|
||||
let configureModeAssociations: IQuickPickItem;
|
||||
let configureModeSettings: IQuickPickItem;
|
||||
let galleryAction: Action;
|
||||
if (hasLanguageSupport) {
|
||||
const ext = paths.extname(resource.fsPath) || paths.basename(resource.fsPath);
|
||||
if (hasLanguageSupport && resource) {
|
||||
const ext = extname(resource) || basename(resource);
|
||||
|
||||
galleryAction = this.instantiationService.createInstance(ShowLanguageExtensionsAction, ext);
|
||||
if (galleryAction.enabled) {
|
||||
@@ -947,7 +945,9 @@ export class ChangeModeAction extends Action {
|
||||
|
||||
// User decided to permanently configure associations, return right after
|
||||
if (pick === configureModeAssociations) {
|
||||
this.configureFileAssociation(resource);
|
||||
if (resource) {
|
||||
this.configureFileAssociation(resource);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -980,10 +980,15 @@ export class ChangeModeAction extends Action {
|
||||
}
|
||||
|
||||
// Find mode
|
||||
let languageSelection: ILanguageSelection;
|
||||
let languageSelection: ILanguageSelection | undefined;
|
||||
if (pick === autoDetectMode) {
|
||||
// {{SQL CARBON EDIT}} - use activeEditor.input instead of activeEditor
|
||||
languageSelection = this.modeService.createByFilepathOrFirstLine(toResource(activeEditor.input, { supportSideBySide: true }).fsPath, textModel.getLineContent(1));
|
||||
if (textModel) {
|
||||
// {{SQL CARBON EDIT}} - use activeEditor.input instead of activeEditor
|
||||
const resource = toResource(activeEditor.input, { supportSideBySide: true });
|
||||
if (resource) {
|
||||
languageSelection = this.modeService.createByFilepathOrFirstLine(resource.fsPath, textModel.getLineContent(1));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
languageSelection = this.modeService.createByLanguageName(pick.label);
|
||||
}
|
||||
@@ -991,10 +996,9 @@ export class ChangeModeAction extends Action {
|
||||
// {{SQL CARBON EDIT}}
|
||||
// Change mode
|
||||
models.forEach(textModel => {
|
||||
let self = this;
|
||||
QueryEditorService.sqlLanguageModeCheck(textModel, languageSelection, activeEditor).then((newTextModel) => {
|
||||
if (newTextModel) {
|
||||
self.modelService.setMode(newTextModel, languageSelection);
|
||||
this.modelService.setMode(newTextModel, languageSelection);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1002,9 +1006,9 @@ export class ChangeModeAction extends Action {
|
||||
}
|
||||
|
||||
private configureFileAssociation(resource: uri): void {
|
||||
const extension = paths.extname(resource.fsPath);
|
||||
const basename = paths.basename(resource.fsPath);
|
||||
const currentAssociation = this.modeService.getModeIdByFilepathOrFirstLine(basename);
|
||||
const extension = extname(resource);
|
||||
const base = basename(resource);
|
||||
const currentAssociation = this.modeService.getModeIdByFilepathOrFirstLine(base);
|
||||
|
||||
const languages = this.modeService.getRegisteredLanguageNames();
|
||||
const picks: IQuickPickItem[] = languages.sort().map((lang, index) => {
|
||||
@@ -1018,15 +1022,15 @@ export class ChangeModeAction extends Action {
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
this.quickInputService.pick(picks, { placeHolder: nls.localize('pickLanguageToConfigure', "Select Language Mode to Associate with '{0}'", extension || basename) }).then(language => {
|
||||
this.quickInputService.pick(picks, { placeHolder: nls.localize('pickLanguageToConfigure', "Select Language Mode to Associate with '{0}'", extension || base) }).then(language => {
|
||||
if (language) {
|
||||
const fileAssociationsConfig = this.configurationService.inspect(FILES_ASSOCIATIONS_CONFIG);
|
||||
|
||||
let associationKey: string;
|
||||
if (extension && basename[0] !== '.') {
|
||||
if (extension && base[0] !== '.') {
|
||||
associationKey = `*${extension}`; // only use "*.ext" if the file path is in the form of <name>.<ext>
|
||||
} else {
|
||||
associationKey = basename; // otherwise use the basename (e.g. .gitignore, Dockerfile)
|
||||
associationKey = base; // otherwise use the basename (e.g. .gitignore, Dockerfile)
|
||||
}
|
||||
|
||||
// If the association is already being made in the workspace, make sure to target workspace settings
|
||||
@@ -1036,11 +1040,7 @@ export class ChangeModeAction extends Action {
|
||||
}
|
||||
|
||||
// Make sure to write into the value of the target and not the merged value from USER and WORKSPACE config
|
||||
let currentAssociations = deepClone((target === ConfigurationTarget.WORKSPACE) ? fileAssociationsConfig.workspace : fileAssociationsConfig.user);
|
||||
if (!currentAssociations) {
|
||||
currentAssociations = Object.create(null);
|
||||
}
|
||||
|
||||
const currentAssociations = deepClone((target === ConfigurationTarget.WORKSPACE) ? fileAssociationsConfig.workspace : fileAssociationsConfig.user) || Object.create(null);
|
||||
currentAssociations[associationKey] = language.id;
|
||||
|
||||
this.configurationService.updateValue(FILES_ASSOCIATIONS_CONFIG, currentAssociations, target);
|
||||
@@ -1089,7 +1089,7 @@ class ChangeIndentationAction extends Action {
|
||||
return {
|
||||
id: a.id,
|
||||
label: a.label,
|
||||
detail: (language === LANGUAGE_DEFAULT) ? null : a.alias,
|
||||
detail: Language.isDefaultVariant() ? undefined : a.alias,
|
||||
run: () => {
|
||||
activeTextEditorWidget.focus();
|
||||
a.run();
|
||||
@@ -1140,7 +1140,7 @@ export class ChangeEOLAction extends Action {
|
||||
return this.quickInputService.pick(EOLOptions, { placeHolder: nls.localize('pickEndOfLine', "Select End of Line Sequence"), activeItem: EOLOptions[selectedIndex] }).then(eol => {
|
||||
if (eol) {
|
||||
const activeCodeEditor = getCodeEditor(this.editorService.activeTextEditorWidget);
|
||||
if (activeCodeEditor && isWritableCodeEditor(activeCodeEditor)) {
|
||||
if (activeCodeEditor && activeCodeEditor.hasModel() && isWritableCodeEditor(activeCodeEditor)) {
|
||||
const textModel = activeCodeEditor.getModel();
|
||||
textModel.pushEOL(eol.eol);
|
||||
}
|
||||
@@ -1170,15 +1170,18 @@ export class ChangeEncodingAction extends Action {
|
||||
return this.quickInputService.pick([{ label: nls.localize('noEditor', "No text editor active at this time") }]);
|
||||
}
|
||||
|
||||
let activeControl = this.editorService.activeControl;
|
||||
let encodingSupport: IEncodingSupport = toEditorWithEncodingSupport(activeControl.input);
|
||||
const activeControl = this.editorService.activeControl;
|
||||
if (!activeControl) {
|
||||
return this.quickInputService.pick([{ label: nls.localize('noEditor', "No text editor active at this time") }]);
|
||||
}
|
||||
const encodingSupport: IEncodingSupport | null = toEditorWithEncodingSupport(activeControl.input);
|
||||
if (!encodingSupport) {
|
||||
return this.quickInputService.pick([{ label: nls.localize('noFileEditor', "No file active at this time") }]);
|
||||
}
|
||||
|
||||
let saveWithEncodingPick: IQuickPickItem;
|
||||
let reopenWithEncodingPick: IQuickPickItem;
|
||||
if (language === LANGUAGE_DEFAULT) {
|
||||
if (Language.isDefaultVariant()) {
|
||||
saveWithEncodingPick = { label: nls.localize('saveWithEncoding', "Save with Encoding") };
|
||||
reopenWithEncodingPick = { label: nls.localize('reopenWithEncoding', "Reopen with Encoding") };
|
||||
} else {
|
||||
@@ -1200,7 +1203,7 @@ export class ChangeEncodingAction extends Action {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const resource = toResource(activeControl.input, { supportSideBySide: true });
|
||||
const resource = toResource(activeControl!.input, { supportSideBySide: true });
|
||||
|
||||
return timeout(50 /* quick open is sensitive to being opened so soon after another */)
|
||||
.then(() => {
|
||||
@@ -1213,10 +1216,10 @@ export class ChangeEncodingAction extends Action {
|
||||
.then((guessedEncoding: string) => {
|
||||
const isReopenWithEncoding = (action === reopenWithEncodingPick);
|
||||
|
||||
const configuredEncoding = this.textResourceConfigurationService.getValue(resource, 'files.encoding');
|
||||
const configuredEncoding = this.textResourceConfigurationService.getValue(types.withNullAsUndefined(resource), 'files.encoding');
|
||||
|
||||
let directMatchIndex: number;
|
||||
let aliasMatchIndex: number;
|
||||
let directMatchIndex: number | undefined;
|
||||
let aliasMatchIndex: number | undefined;
|
||||
|
||||
// All encodings are valid picks
|
||||
const picks: QuickPickInput[] = Object.keys(SUPPORTED_ENCODINGS)
|
||||
@@ -1258,12 +1261,16 @@ export class ChangeEncodingAction extends Action {
|
||||
placeHolder: isReopenWithEncoding ? nls.localize('pickEncodingForReopen', "Select File Encoding to Reopen File") : nls.localize('pickEncodingForSave', "Select File Encoding to Save with"),
|
||||
activeItem: items[typeof directMatchIndex === 'number' ? directMatchIndex : typeof aliasMatchIndex === 'number' ? aliasMatchIndex : -1]
|
||||
}).then(encoding => {
|
||||
if (encoding) {
|
||||
activeControl = this.editorService.activeControl;
|
||||
encodingSupport = toEditorWithEncodingSupport(activeControl.input);
|
||||
if (encodingSupport && encodingSupport.getEncoding() !== encoding.id) {
|
||||
encodingSupport.setEncoding(encoding.id, isReopenWithEncoding ? EncodingMode.Decode : EncodingMode.Encode); // Set new encoding
|
||||
}
|
||||
if (!encoding) {
|
||||
return;
|
||||
}
|
||||
const activeControl = this.editorService.activeControl;
|
||||
if (!activeControl) {
|
||||
return;
|
||||
}
|
||||
const encodingSupport = toEditorWithEncodingSupport(activeControl.input);
|
||||
if (typeof encoding.id !== 'undefined' && encodingSupport && encodingSupport.getEncoding() !== encoding.id) {
|
||||
encodingSupport.setEncoding(encoding.id, isReopenWithEncoding ? EncodingMode.Decode : EncodingMode.Encode); // Set new encoding
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -14,17 +14,16 @@ import { buttonBackground, buttonForeground, editorBackground, editorForeground,
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IWindowService } from 'vs/platform/windows/common/windows';
|
||||
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { WORKSPACE_EXTENSION } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { extname } from 'vs/base/common/paths';
|
||||
import { hasWorkspaceFileExtension } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { Disposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IEditorContribution } from 'vs/editor/common/editorCommon';
|
||||
import { isEqual } from 'vs/base/common/resources';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
|
||||
export class FloatingClickWidget extends Widget implements IOverlayWidget {
|
||||
|
||||
private _onClick: Emitter<void> = this._register(new Emitter<void>());
|
||||
private readonly _onClick: Emitter<void> = this._register(new Emitter<void>());
|
||||
get onClick(): Event<void> { return this._onClick.event; }
|
||||
|
||||
private _domNode: HTMLElement;
|
||||
@@ -108,7 +107,8 @@ export class OpenWorkspaceButtonContribution extends Disposable implements IEdit
|
||||
private editor: ICodeEditor,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IWindowService private readonly windowService: IWindowService,
|
||||
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService
|
||||
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
|
||||
@IFileService private readonly fileService: IFileService
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -139,8 +139,12 @@ export class OpenWorkspaceButtonContribution extends Disposable implements IEdit
|
||||
return false; // we need a model
|
||||
}
|
||||
|
||||
if (model.uri.scheme !== Schemas.file || extname(model.uri.fsPath) !== `.${WORKSPACE_EXTENSION}`) {
|
||||
return false; // we need a local workspace file
|
||||
if (!hasWorkspaceFileExtension(model.uri.fsPath)) {
|
||||
return false; // we need a workspace file
|
||||
}
|
||||
|
||||
if (!this.fileService.canHandleResource(model.uri)) {
|
||||
return false; // needs to be backed by a file service
|
||||
}
|
||||
|
||||
if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) {
|
||||
@@ -159,7 +163,7 @@ export class OpenWorkspaceButtonContribution extends Disposable implements IEdit
|
||||
this._register(this.openWorkspaceButton.onClick(() => {
|
||||
const model = this.editor.getModel();
|
||||
if (model) {
|
||||
this.windowService.openWindow([model.uri]);
|
||||
this.windowService.openWindow([{ uri: model.uri, typeHint: 'file' }]);
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{opacity:0.2;}
|
||||
.st1{fill:#646464;}
|
||||
</style>
|
||||
<g class="st0">
|
||||
<path class="st1" d="M12.7,19.2L12.1,19H7l-1.4,3.8L3.1,16L2,19H0v1.5C0,22.4,3.1,24,7,24c2.3,0,4.3-0.6,5.6-1.4l-0.1-0.3l-0.4-0.9
|
||||
l-0.4-0.9l0.9-0.4l0.3-0.1c0-0.1,0-0.2,0-0.2c0-0.1,0-0.2,0-0.2L12.7,19.2z"/>
|
||||
<path class="st1" d="M12.5,11c-1.3,0.8-3.3,1.3-5.5,1.3c-3.9,0-7-1.6-7-3.5V18h1.3l1.8-5l2.5,6.8L6.3,18h5.8l0-0.1l0.4-0.9l0.4-0.9
|
||||
l0.9,0.4l0.2,0.1V11L12.5,11L12.5,11z"/>
|
||||
<g>
|
||||
<path class="st1" d="M19,4c0.4,0,0.8,0.1,1.2,0.2c0.4,0.2,0.7,0.4,1,0.6c0.3,0.3,0.5,0.6,0.6,0.9C21.9,6.2,22,6.6,22,7
|
||||
c0,0.4-0.1,0.8-0.2,1.2c-0.2,0.4-0.4,0.7-0.6,1c-0.3,0.3-0.6,0.5-1,0.6C19.8,9.9,19.4,10,19,10h-9c-0.6,0-1.1-0.1-1.6-0.3
|
||||
C8,9.5,7.5,9.2,7.2,8.8C6.8,8.5,6.5,8,6.3,7.6C6.1,7.1,6,6.6,6,6c0-0.6,0.1-1.1,0.3-1.6C6.5,4,6.8,3.5,7.2,3.2
|
||||
c0.4-0.4,0.8-0.6,1.3-0.9C8.9,2.1,9.4,2,10,2c0.2,0,0.5,0,0.7,0.1c0.2-0.3,0.4-0.6,0.7-0.9c0.3-0.3,0.6-0.5,0.9-0.7
|
||||
c0.3-0.2,0.7-0.3,1-0.4C13.7,0.1,14.1,0,14.5,0c0.6,0,1.1,0.1,1.6,0.3c0.5,0.2,1,0.5,1.4,0.8c0.4,0.4,0.7,0.8,1,1.3
|
||||
C18.7,2.9,18.9,3.4,19,4z"/>
|
||||
</g>
|
||||
<path class="st1" d="M21,19.5c0,0.3,0,0.6-0.1,0.9l1.1,0.4l-0.4,0.9l-1.1-0.4c-0.3,0.5-0.7,0.9-1.2,1.2l0.4,1.1L18.8,24l-0.4-1.1
|
||||
C18.1,23,17.8,23,17.5,23s-0.6,0-0.9-0.1L16.2,24l-0.9-0.4l0.4-1.1c-0.5-0.3-0.9-0.7-1.2-1.2l-1.1,0.4L13,20.8l1.1-0.4
|
||||
C14,20.1,14,19.8,14,19.5s0-0.6,0.1-0.9L13,18.2l0.4-0.9l1.1,0.4c0.3-0.5,0.7-0.9,1.2-1.2l-0.4-1.1l0.9-0.4l0.4,1.1
|
||||
c0.3-0.1,0.6-0.1,0.9-0.1s0.6,0,0.9,0.1l0.4-1.1l0.9,0.4l-0.4,1.1c0.5,0.3,0.9,0.7,1.2,1.2l1.1-0.4l0.4,0.9l-1.1,0.4
|
||||
C21,19,21,19.2,21,19.5z M17.5,22c0.3,0,0.7-0.1,1-0.2c0.3-0.1,0.6-0.3,0.8-0.5s0.4-0.5,0.5-0.8c0.1-0.3,0.2-0.6,0.2-1
|
||||
s-0.1-0.7-0.2-1c-0.1-0.3-0.3-0.6-0.5-0.8s-0.5-0.4-0.8-0.5c-0.3-0.1-0.6-0.2-1-0.2c-0.3,0-0.7,0.1-1,0.2c-0.3,0.1-0.6,0.3-0.8,0.5
|
||||
c-0.2,0.2-0.4,0.5-0.5,0.8c-0.1,0.3-0.2,0.6-0.2,1c0,0.3,0.1,0.7,0.2,1c0.1,0.3,0.3,0.6,0.5,0.8s0.5,0.4,0.8,0.5
|
||||
C16.8,22,17.1,22,17.5,22z"/>
|
||||
<path class="st1" d="M9.9,11c-0.6,0-1.3-0.1-1.8-0.4C7.4,10.4,6.9,10,6.5,9.5C6,9.1,5.7,8.6,5.4,8C5.2,7.5,5.1,7,5,6.5
|
||||
C2.5,6.9,1,8,1,8.8c0,1,2.3,2.5,6,2.5C8,11.3,9,11.2,9.9,11z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="24px" height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<g>
|
||||
<path style="fill:#646464;" d="M12.654,19.244l-0.572-0.236H6.958l-1.374,3.777l-2.48-6.824l-1.108,3.047H0v1.488
|
||||
c0,1.932,3.131,3.496,6.997,3.496c2.304,0,4.348-0.555,5.621-1.416l-0.139-0.346l-0.377-0.93l-0.371-0.924l0.922-0.375l0.348-0.143
|
||||
c-0.005-0.08-0.007-0.158-0.007-0.236c0-0.08,0.002-0.16,0.007-0.238L12.654,19.244z"/>
|
||||
<path style="fill:#646464;" d="M12.491,10.999c-1.28,0.812-3.265,1.334-5.494,1.334C3.132,12.333,0,10.766,0,8.833v9.175h1.296
|
||||
l1.808-4.973l2.48,6.824l0.675-1.852h5.822l0.024-0.064l0.376-0.93l0.377-0.934l0.931,0.383l0.204,0.086v-5.55H12.491z"/>
|
||||
<g>
|
||||
<path style="fill:#646464;" d="M18.968,4.002c0.419,0,0.809,0.078,1.175,0.234c0.368,0.156,0.688,0.369,0.962,0.636
|
||||
c0.274,0.27,0.49,0.586,0.647,0.949C21.91,6.188,21.99,6.578,21.99,7c0,0.418-0.078,0.806-0.234,1.168
|
||||
c-0.155,0.362-0.371,0.68-0.645,0.952c-0.273,0.273-0.593,0.488-0.955,0.645c-0.365,0.158-0.755,0.234-1.164,0.234H9.995
|
||||
c-0.551,0-1.069-0.104-1.558-0.312C7.951,9.48,7.526,9.195,7.164,8.833c-0.36-0.36-0.646-0.786-0.854-1.272
|
||||
c-0.209-0.487-0.312-1.008-0.312-1.56c0-0.551,0.104-1.069,0.312-1.559c0.206-0.484,0.492-0.91,0.854-1.272
|
||||
C7.526,2.809,7.95,2.523,8.437,2.314c0.489-0.208,1.008-0.312,1.559-0.312c0.237,0,0.48,0.023,0.727,0.071
|
||||
c0.209-0.322,0.448-0.613,0.722-0.871c0.276-0.258,0.572-0.474,0.897-0.651c0.321-0.176,0.666-0.312,1.028-0.407
|
||||
c0.365-0.093,0.738-0.14,1.125-0.14c0.577,0,1.122,0.101,1.636,0.305c0.513,0.203,0.968,0.483,1.362,0.839
|
||||
c0.396,0.357,0.723,0.781,0.98,1.271C18.729,2.906,18.893,3.437,18.968,4.002z"/>
|
||||
</g>
|
||||
<path style="fill:#646464;" d="M20.991,19.537c0,0.287-0.037,0.576-0.109,0.867l1.068,0.436l-0.374,0.93l-1.079-0.445
|
||||
c-0.308,0.512-0.712,0.918-1.216,1.221l0.445,1.066l-0.93,0.385l-0.439-1.07c-0.291,0.074-0.58,0.109-0.867,0.109
|
||||
S16.915,23,16.623,22.926l-0.437,1.07l-0.929-0.385l0.444-1.066c-0.511-0.303-0.918-0.709-1.219-1.221l-1.078,0.445l-0.373-0.93
|
||||
l1.069-0.436c-0.072-0.291-0.108-0.58-0.108-0.867s0.036-0.574,0.111-0.867l-1.071-0.438l0.374-0.93l1.079,0.443
|
||||
c0.3-0.504,0.706-0.91,1.218-1.217l-0.445-1.078l0.931-0.375l0.437,1.068c0.29-0.072,0.58-0.107,0.866-0.107
|
||||
s0.577,0.035,0.867,0.107l0.438-1.068l0.93,0.375l-0.444,1.078c0.503,0.307,0.908,0.713,1.217,1.217l1.078-0.443l0.374,0.93
|
||||
l-1.068,0.438C20.954,18.963,20.991,19.25,20.991,19.537z M17.492,22.035c0.344,0,0.666-0.064,0.969-0.195
|
||||
c0.302-0.129,0.566-0.309,0.792-0.535s0.407-0.492,0.539-0.797c0.133-0.303,0.199-0.627,0.199-0.971s-0.066-0.666-0.199-0.969
|
||||
c-0.132-0.303-0.313-0.566-0.539-0.793s-0.49-0.406-0.792-0.539c-0.303-0.133-0.625-0.199-0.969-0.199
|
||||
c-0.343,0-0.667,0.066-0.973,0.199c-0.304,0.133-0.568,0.312-0.797,0.539c-0.228,0.227-0.404,0.49-0.534,0.793
|
||||
c-0.131,0.303-0.195,0.625-0.195,0.969c0,0.342,0.064,0.668,0.195,0.971c0.13,0.305,0.309,0.57,0.534,0.797
|
||||
s0.493,0.406,0.797,0.535C16.825,21.971,17.149,22.035,17.492,22.035z"/>
|
||||
<path style="fill:#646464;" d="M9.886,10.988c-0.644-0.014-1.265-0.136-1.839-0.383C7.443,10.351,6.91,9.992,6.458,9.54
|
||||
C6.01,9.092,5.65,8.558,5.391,7.954C5.193,7.492,5.094,6.997,5.045,6.487C2.525,6.88,1,7.981,1,8.833c0,1.044,2.281,2.5,5.997,2.5
|
||||
C8.014,11.333,9.004,11.209,9.886,10.988z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
39
src/vs/workbench/browser/parts/editor/media/letterpress.svg
Normal file
39
src/vs/workbench/browser/parts/editor/media/letterpress.svg
Normal file
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="24px" height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<g style="opacity:0.2;">
|
||||
<path style="fill:#646464;" d="M12.654,19.244l-0.572-0.236H6.958l-1.374,3.777l-2.48-6.824l-1.108,3.047H0v1.488
|
||||
c0,1.932,3.131,3.496,6.997,3.496c2.304,0,4.348-0.555,5.621-1.416l-0.139-0.346l-0.377-0.93l-0.371-0.924l0.922-0.375l0.348-0.143
|
||||
c-0.005-0.08-0.007-0.158-0.007-0.236c0-0.08,0.002-0.16,0.007-0.238L12.654,19.244z"/>
|
||||
<path style="fill:#646464;" d="M12.491,10.999c-1.28,0.812-3.265,1.334-5.494,1.334C3.132,12.333,0,10.766,0,8.833v9.174h1.296
|
||||
l1.808-4.973l2.48,6.824l0.675-1.852h5.822l0.024-0.064l0.376-0.93l0.377-0.934l0.931,0.383l0.204,0.086v-5.55H12.491z"/>
|
||||
<g>
|
||||
<path style="fill:#646464;" d="M18.968,4.002c0.419,0,0.809,0.078,1.175,0.234c0.368,0.156,0.688,0.369,0.962,0.636
|
||||
c0.274,0.27,0.49,0.586,0.647,0.949C21.91,6.188,21.99,6.579,21.99,7c0,0.418-0.078,0.806-0.234,1.168
|
||||
c-0.155,0.363-0.371,0.68-0.645,0.953s-0.593,0.488-0.955,0.645c-0.365,0.158-0.755,0.234-1.164,0.234H9.995
|
||||
c-0.551,0-1.069-0.103-1.558-0.312C7.951,9.48,7.526,9.195,7.164,8.833C6.804,8.473,6.518,8.047,6.31,7.561
|
||||
c-0.209-0.488-0.312-1.008-0.312-1.56c0-0.551,0.104-1.069,0.312-1.559c0.206-0.484,0.492-0.91,0.854-1.272
|
||||
C7.526,2.809,7.95,2.524,8.437,2.315c0.489-0.208,1.008-0.312,1.559-0.312c0.237,0,0.48,0.023,0.727,0.071
|
||||
c0.209-0.322,0.448-0.613,0.722-0.871c0.276-0.258,0.572-0.474,0.897-0.652c0.321-0.176,0.666-0.312,1.028-0.407
|
||||
c0.365-0.093,0.738-0.14,1.125-0.14c0.577,0,1.122,0.1,1.636,0.304c0.513,0.203,0.968,0.483,1.362,0.839
|
||||
c0.396,0.357,0.723,0.782,0.98,1.271C18.729,2.907,18.893,3.437,18.968,4.002z"/>
|
||||
</g>
|
||||
<path style="fill:#646464;" d="M20.991,19.537c0,0.287-0.037,0.576-0.109,0.867l1.068,0.436l-0.374,0.93l-1.079-0.445
|
||||
c-0.308,0.512-0.712,0.918-1.216,1.221l0.445,1.066l-0.93,0.385l-0.439-1.07c-0.291,0.074-0.58,0.109-0.867,0.109
|
||||
S16.915,23,16.623,22.926l-0.437,1.07l-0.929-0.385l0.444-1.066c-0.511-0.303-0.918-0.709-1.219-1.221l-1.078,0.445l-0.373-0.93
|
||||
l1.069-0.436c-0.072-0.291-0.108-0.58-0.108-0.867s0.036-0.574,0.111-0.867l-1.071-0.438l0.374-0.93l1.079,0.443
|
||||
c0.3-0.504,0.706-0.91,1.218-1.217l-0.445-1.078l0.931-0.375l0.437,1.068c0.29-0.072,0.58-0.107,0.866-0.107
|
||||
s0.577,0.035,0.867,0.107l0.438-1.068l0.93,0.375l-0.444,1.078c0.503,0.307,0.908,0.713,1.217,1.217l1.078-0.443l0.374,0.93
|
||||
l-1.068,0.438C20.954,18.963,20.991,19.25,20.991,19.537z M17.492,22.035c0.344,0,0.666-0.064,0.969-0.195
|
||||
c0.302-0.129,0.566-0.309,0.792-0.535s0.407-0.492,0.539-0.797c0.133-0.303,0.199-0.627,0.199-0.971s-0.066-0.666-0.199-0.969
|
||||
c-0.132-0.303-0.313-0.566-0.539-0.793s-0.49-0.406-0.792-0.539c-0.303-0.133-0.625-0.199-0.969-0.199
|
||||
c-0.343,0-0.667,0.066-0.973,0.199c-0.304,0.133-0.568,0.312-0.797,0.539c-0.228,0.227-0.404,0.49-0.534,0.793
|
||||
c-0.131,0.303-0.195,0.625-0.195,0.969c0,0.342,0.064,0.668,0.195,0.971c0.13,0.305,0.309,0.57,0.534,0.797
|
||||
s0.493,0.406,0.797,0.535C16.825,21.971,17.149,22.035,17.492,22.035z"/>
|
||||
<path style="fill:#646464;" d="M9.886,10.988c-0.644-0.014-1.265-0.135-1.839-0.382C7.443,10.351,6.91,9.992,6.458,9.541
|
||||
C6.01,9.092,5.65,8.558,5.391,7.954C5.193,7.493,5.094,6.997,5.045,6.488C2.525,6.88,1,7.982,1,8.833c0,1.044,2.281,2.5,5.997,2.5
|
||||
C8.014,11.333,9.004,11.209,9.886,10.988z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
@@ -54,15 +54,14 @@
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
/* {{SQL CARBON EDIT}} */
|
||||
.windows > .monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item::before {
|
||||
content: '/';
|
||||
.monaco-workbench.windows .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item::before {
|
||||
content: '\\';
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item.root_folder::before,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item.root_folder + .monaco-breadcrumb-item::before,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control.relative-path .monaco-breadcrumb-item:nth-child(2)::before,
|
||||
.windows > .monaco-workbench .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item:nth-child(2)::before {
|
||||
.monaco-workbench.windows .part.editor > .content .editor-group-container > .title.breadcrumbs .breadcrumbs-control .monaco-breadcrumb-item:nth-child(2)::before {
|
||||
/* workspace folder, item following workspace folder, or relative path -> hide first seperator */
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -4,19 +4,20 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./media/notabstitlecontrol';
|
||||
import { toResource, Verbosity, IEditorInput } from 'vs/workbench/common/editor';
|
||||
import { toResource, Verbosity, IEditorInput, IEditorPartOptions } from 'vs/workbench/common/editor';
|
||||
import { TitleControl, IToolbarActions } from 'vs/workbench/browser/parts/editor/titleControl';
|
||||
import { ResourceLabel, IResourceLabel } from 'vs/workbench/browser/labels';
|
||||
import { TAB_ACTIVE_FOREGROUND, TAB_UNFOCUSED_ACTIVE_FOREGROUND } from 'vs/workbench/common/theme';
|
||||
import { EventType as TouchEventType, GestureEvent, Gesture } from 'vs/base/browser/touch';
|
||||
import { addDisposableListener, EventType, addClass, EventHelper, removeClass, toggleClass } from 'vs/base/browser/dom';
|
||||
import { IEditorPartOptions, EDITOR_TITLE_HEIGHT } from 'vs/workbench/browser/parts/editor/editor';
|
||||
import { EDITOR_TITLE_HEIGHT } from 'vs/workbench/browser/parts/editor/editor';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { CLOSE_EDITOR_COMMAND_ID } from 'vs/workbench/browser/parts/editor/editorCommands';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
|
||||
interface IRenderedEditorLabel {
|
||||
editor: IEditorInput;
|
||||
editor?: IEditorInput;
|
||||
pinned: boolean;
|
||||
}
|
||||
|
||||
@@ -72,8 +73,16 @@ export class NoTabsTitleControl extends TitleControl {
|
||||
this._register(addDisposableListener(this.titleContainer, TouchEventType.Tap, (e: GestureEvent) => this.onTitleClick(e)));
|
||||
|
||||
// Context Menu
|
||||
this._register(addDisposableListener(this.titleContainer, EventType.CONTEXT_MENU, (e: Event) => this.onContextMenu(this.group.activeEditor, e, this.titleContainer)));
|
||||
this._register(addDisposableListener(this.titleContainer, TouchEventType.Contextmenu, (e: Event) => this.onContextMenu(this.group.activeEditor, e, this.titleContainer)));
|
||||
this._register(addDisposableListener(this.titleContainer, EventType.CONTEXT_MENU, (e: Event) => {
|
||||
if (this.group.activeEditor) {
|
||||
this.onContextMenu(this.group.activeEditor, e, this.titleContainer);
|
||||
}
|
||||
}));
|
||||
this._register(addDisposableListener(this.titleContainer, TouchEventType.Contextmenu, (e: Event) => {
|
||||
if (this.group.activeEditor) {
|
||||
this.onContextMenu(this.group.activeEditor, e, this.titleContainer);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private onTitleLabelClick(e: MouseEvent): void {
|
||||
@@ -95,7 +104,9 @@ export class NoTabsTitleControl extends TitleControl {
|
||||
if (e instanceof MouseEvent && e.button === 1 /* Middle Button */) {
|
||||
EventHelper.stop(e, true /* for https://github.com/Microsoft/vscode/issues/56715 */);
|
||||
|
||||
this.group.closeEditor(this.group.activeEditor);
|
||||
if (this.group.activeEditor) {
|
||||
this.group.closeEditor(this.group.activeEditor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,7 +178,7 @@ export class NoTabsTitleControl extends TitleControl {
|
||||
if (
|
||||
!this.activeLabel.editor && this.group.activeEditor || // active editor changed from null => editor
|
||||
this.activeLabel.editor && !this.group.activeEditor || // active editor changed from editor => null
|
||||
!this.group.isActive(this.activeLabel.editor) // active editor changed from editorA => editorB
|
||||
(!this.activeLabel.editor || !this.group.isActive(this.activeLabel.editor)) // active editor changed from editorA => editorB
|
||||
) {
|
||||
fn();
|
||||
|
||||
@@ -195,9 +206,9 @@ export class NoTabsTitleControl extends TitleControl {
|
||||
}
|
||||
|
||||
private redraw(): void {
|
||||
const editor = this.group.activeEditor;
|
||||
const editor = withNullAsUndefined(this.group.activeEditor);
|
||||
|
||||
const isEditorPinned = this.group.isPinned(this.group.activeEditor);
|
||||
const isEditorPinned = this.group.activeEditor ? this.group.isPinned(this.group.activeEditor) : false;
|
||||
const isGroupActive = this.accessor.activeGroup === this.group;
|
||||
|
||||
this.activeLabel = { editor, pinned: isEditorPinned };
|
||||
@@ -244,7 +255,7 @@ export class NoTabsTitleControl extends TitleControl {
|
||||
title = ''; // dont repeat what is already shown
|
||||
}
|
||||
|
||||
this.editorLabel.setResource({ name, description, resource }, { title, italic: !isEditorPinned, extraClasses: ['no-tabs', 'title-label'] });
|
||||
this.editorLabel.setResource({ name, description, resource: resource || undefined }, { title: typeof title === 'string' ? title : undefined, italic: !isEditorPinned, extraClasses: ['no-tabs', 'title-label'] });
|
||||
if (isGroupActive) {
|
||||
this.editorLabel.element.style.color = this.getColor(TAB_ACTIVE_FOREGROUND);
|
||||
} else {
|
||||
@@ -256,7 +267,7 @@ export class NoTabsTitleControl extends TitleControl {
|
||||
}
|
||||
}
|
||||
|
||||
private getVerbosity(style: string): Verbosity {
|
||||
private getVerbosity(style: string | undefined): Verbosity {
|
||||
switch (style) {
|
||||
case 'short': return Verbosity.SHORT;
|
||||
case 'long': return Verbosity.LONG;
|
||||
|
||||
@@ -27,7 +27,7 @@ export interface IResourceDescriptor {
|
||||
readonly resource: URI;
|
||||
readonly name: string;
|
||||
readonly size: number;
|
||||
readonly etag: string;
|
||||
readonly etag?: string;
|
||||
readonly mime: string;
|
||||
}
|
||||
|
||||
@@ -236,7 +236,7 @@ export class ZoomStatusbarItem extends Themable implements IStatusbarItem {
|
||||
|
||||
static instance: ZoomStatusbarItem;
|
||||
|
||||
showTimeout: any;
|
||||
private showTimeout: any;
|
||||
|
||||
private statusBarItem: HTMLElement;
|
||||
private onSelectScale?: (scale: Scale) => void;
|
||||
|
||||
@@ -13,7 +13,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { scrollbarShadow } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { IEditorRegistry, Extensions as EditorExtensions } from 'vs/workbench/browser/editor';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { IEditorGroup } from 'vs/workbench/services/group/common/editorGroupsService';
|
||||
import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { SplitView, Sizing, Orientation } from 'vs/base/browser/ui/splitview/splitview';
|
||||
import { Event, Relay, Emitter } from 'vs/base/common/event';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import 'vs/css!./media/tabstitlecontrol';
|
||||
import { isMacintosh } from 'vs/base/common/platform';
|
||||
import { shorten } from 'vs/base/common/labels';
|
||||
import { toResource, GroupIdentifier, IEditorInput, Verbosity, EditorCommandsContextActionRunner } from 'vs/workbench/common/editor';
|
||||
import { toResource, GroupIdentifier, IEditorInput, Verbosity, EditorCommandsContextActionRunner, IEditorPartOptions } from 'vs/workbench/common/editor';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { EventType as TouchEventType, GestureEvent, Gesture } from 'vs/base/browser/touch';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
@@ -32,25 +32,22 @@ import { ResourcesDropHandler, fillResourceDataTransfers, DraggedEditorIdentifie
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { MergeGroupMode, IMergeGroupOptions } from 'vs/workbench/services/group/common/editorGroupsService';
|
||||
import { MergeGroupMode, IMergeGroupOptions } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
|
||||
import { addClass, addDisposableListener, hasClass, EventType, EventHelper, removeClass, Dimension, scheduleAtNextAnimationFrame, findParentWithClass, clearNode } from 'vs/base/browser/dom';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IEditorGroupsAccessor, IEditorPartOptions, IEditorGroupView } from 'vs/workbench/browser/parts/editor/editor';
|
||||
import { IEditorGroupsAccessor, IEditorGroupView } from 'vs/workbench/browser/parts/editor/editor';
|
||||
import { CloseOneEditorAction } from 'vs/workbench/browser/parts/editor/editorActions';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { BreadcrumbsControl } from 'vs/workbench/browser/parts/editor/breadcrumbsControl';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
|
||||
// {{SQL CARBON EDIT}} -- Display the editor's tab color
|
||||
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
|
||||
import { IQueryEditorService } from 'sql/workbench/services/queryEditor/common/queryEditorService';
|
||||
import { IObjectExplorerService } from 'sql/workbench/services/objectExplorer/common/objectExplorerService';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { GlobalNewUntitledFileAction } from 'vs/workbench/parts/files/electron-browser/fileActions';
|
||||
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import * as QueryConstants from 'sql/parts/query/common/constants';
|
||||
import * as WorkbenchUtils from 'sql/workbench/common/sqlWorkbenchUtils';
|
||||
import { GlobalNewUntitledFileAction } from 'vs/workbench/contrib/files/browser/fileActions';
|
||||
// {{SQL CARBON EDIT}} -- End
|
||||
|
||||
interface IEditorInputLabel {
|
||||
@@ -74,7 +71,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
private tabDisposeables: IDisposable[] = [];
|
||||
|
||||
private dimension: Dimension;
|
||||
private layoutScheduled: IDisposable;
|
||||
private layoutScheduled?: IDisposable;
|
||||
private blockRevealActiveTab: boolean;
|
||||
|
||||
constructor(
|
||||
@@ -95,11 +92,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@IFileService fileService: IFileService,
|
||||
// {{SQL CARBON EDIT}} -- Display the editor's tab color
|
||||
@IWorkspaceConfigurationService private workspaceConfigurationService: IWorkspaceConfigurationService,
|
||||
@ICommandService private commandService: ICommandService,
|
||||
@IConnectionManagementService private connectionService: IConnectionManagementService,
|
||||
@IQueryEditorService private queryEditorService: IQueryEditorService,
|
||||
@IObjectExplorerService private objectExplorerService: IObjectExplorerService,
|
||||
// {{SQL CARBON EDIT}} -- End
|
||||
) {
|
||||
super(parent, accessor, group, contextMenuService, instantiationService, contextKeyService, keybindingService, telemetryService, notificationService, menuService, quickOpenService, themeService, extensionService, configurationService, fileService);
|
||||
@@ -222,7 +215,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
|
||||
// Return if transfer is unsupported
|
||||
if (!this.isSupportedDropTransfer(e)) {
|
||||
e.dataTransfer.dropEffect = 'none';
|
||||
e.dataTransfer!.dropEffect = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -231,9 +224,9 @@ export class TabsTitleControl extends TitleControl {
|
||||
if (this.editorTransfer.hasData(DraggedEditorIdentifier.prototype)) {
|
||||
isLocalDragAndDrop = true;
|
||||
|
||||
const localDraggedEditor = this.editorTransfer.getData(DraggedEditorIdentifier.prototype)[0].identifier;
|
||||
const localDraggedEditor = this.editorTransfer.getData(DraggedEditorIdentifier.prototype)![0].identifier;
|
||||
if (this.group.id === localDraggedEditor.groupId && this.group.getIndexOfEditor(localDraggedEditor.editor) === this.group.count - 1) {
|
||||
e.dataTransfer.dropEffect = 'none';
|
||||
e.dataTransfer!.dropEffect = 'none';
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -241,7 +234,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
// Update the dropEffect to "copy" if there is no local data to be dragged because
|
||||
// in that case we can only copy the data into and not move it from its source
|
||||
if (!isLocalDragAndDrop) {
|
||||
e.dataTransfer.dropEffect = 'copy';
|
||||
e.dataTransfer!.dropEffect = 'copy';
|
||||
}
|
||||
|
||||
this.updateDropFeedback(this.tabsContainer, true);
|
||||
@@ -317,7 +310,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
(this.tabsContainer.lastChild as HTMLElement).remove();
|
||||
|
||||
// Remove associated tab label and widget
|
||||
this.tabDisposeables.pop().dispose();
|
||||
this.tabDisposeables.pop()!.dispose();
|
||||
}
|
||||
|
||||
// A removal of a label requires to recompute all labels
|
||||
@@ -488,7 +481,10 @@ export class TabsTitleControl extends TitleControl {
|
||||
}
|
||||
|
||||
// Open tabs editor
|
||||
this.group.openEditor(this.group.getEditor(index));
|
||||
const input = this.group.getEditor(index);
|
||||
if (input) {
|
||||
this.group.openEditor(input);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
@@ -496,7 +492,10 @@ export class TabsTitleControl extends TitleControl {
|
||||
const showContextMenu = (e: Event) => {
|
||||
EventHelper.stop(e);
|
||||
|
||||
this.onContextMenu(this.group.getEditor(index), e, tab);
|
||||
const input = this.group.getEditor(index);
|
||||
if (input) {
|
||||
this.onContextMenu(input, e, tab);
|
||||
}
|
||||
};
|
||||
|
||||
// Open on Click / Touch
|
||||
@@ -543,7 +542,10 @@ export class TabsTitleControl extends TitleControl {
|
||||
// Run action on Enter/Space
|
||||
if (event.equals(KeyCode.Enter) || event.equals(KeyCode.Space)) {
|
||||
handled = true;
|
||||
this.group.openEditor(this.group.getEditor(index));
|
||||
const input = this.group.getEditor(index);
|
||||
if (input) {
|
||||
this.group.openEditor(input);
|
||||
}
|
||||
}
|
||||
|
||||
// Navigate in editors
|
||||
@@ -581,22 +583,29 @@ export class TabsTitleControl extends TitleControl {
|
||||
disposables.push(addDisposableListener(tab, EventType.DBLCLICK, (e: MouseEvent) => {
|
||||
EventHelper.stop(e);
|
||||
|
||||
this.group.pinEditor(this.group.getEditor(index));
|
||||
this.group.pinEditor(this.group.getEditor(index) || undefined);
|
||||
}));
|
||||
|
||||
// Context menu
|
||||
disposables.push(addDisposableListener(tab, EventType.CONTEXT_MENU, (e: Event) => {
|
||||
EventHelper.stop(e, true);
|
||||
|
||||
this.onContextMenu(this.group.getEditor(index), e, tab);
|
||||
const input = this.group.getEditor(index);
|
||||
if (input) {
|
||||
this.onContextMenu(input, e, tab);
|
||||
}
|
||||
}, true /* use capture to fix https://github.com/Microsoft/vscode/issues/19145 */));
|
||||
|
||||
// Drag support
|
||||
disposables.push(addDisposableListener(tab, EventType.DRAG_START, (e: DragEvent) => {
|
||||
const editor = this.group.getEditor(index);
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.editorTransfer.setData([new DraggedEditorIdentifier({ editor, groupId: this.group.id })], DraggedEditorIdentifier.prototype);
|
||||
|
||||
e.dataTransfer.effectAllowed = 'copyMove';
|
||||
e.dataTransfer!.effectAllowed = 'copyMove';
|
||||
|
||||
// Apply some datatransfer types to allow for dragging the element outside of the application
|
||||
const resource = toResource(editor, { supportSideBySide: true });
|
||||
@@ -618,7 +627,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
|
||||
// Return if transfer is unsupported
|
||||
if (!this.isSupportedDropTransfer(e)) {
|
||||
e.dataTransfer.dropEffect = 'none';
|
||||
e.dataTransfer!.dropEffect = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -627,9 +636,9 @@ export class TabsTitleControl extends TitleControl {
|
||||
if (this.editorTransfer.hasData(DraggedEditorIdentifier.prototype)) {
|
||||
isLocalDragAndDrop = true;
|
||||
|
||||
const localDraggedEditor = this.editorTransfer.getData(DraggedEditorIdentifier.prototype)[0].identifier;
|
||||
const localDraggedEditor = this.editorTransfer.getData(DraggedEditorIdentifier.prototype)![0].identifier;
|
||||
if (localDraggedEditor.editor === this.group.getEditor(index) && localDraggedEditor.groupId === this.group.id) {
|
||||
e.dataTransfer.dropEffect = 'none';
|
||||
e.dataTransfer!.dropEffect = 'none';
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -637,7 +646,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
// Update the dropEffect to "copy" if there is no local data to be dragged because
|
||||
// in that case we can only copy the data into and not move it from its source
|
||||
if (!isLocalDragAndDrop) {
|
||||
e.dataTransfer.dropEffect = 'copy';
|
||||
e.dataTransfer!.dropEffect = 'copy';
|
||||
}
|
||||
|
||||
this.updateDropFeedback(tab, true, index);
|
||||
@@ -668,7 +677,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
|
||||
private isSupportedDropTransfer(e: DragEvent): boolean {
|
||||
if (this.groupTransfer.hasData(DraggedEditorGroupIdentifier.prototype)) {
|
||||
const group = this.groupTransfer.getData(DraggedEditorGroupIdentifier.prototype)[0];
|
||||
const group = this.groupTransfer.getData(DraggedEditorGroupIdentifier.prototype)![0];
|
||||
if (group.identifier === this.group.id) {
|
||||
return false; // groups cannot be dropped on title area it originates from
|
||||
}
|
||||
@@ -680,7 +689,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
return true; // (local) editors can always be dropped
|
||||
}
|
||||
|
||||
if (e.dataTransfer.types.length > 0) {
|
||||
if (e.dataTransfer && e.dataTransfer.types.length > 0) {
|
||||
return true; // optimistically allow external data (// see https://github.com/Microsoft/vscode/issues/25789)
|
||||
}
|
||||
|
||||
@@ -689,7 +698,8 @@ export class TabsTitleControl extends TitleControl {
|
||||
|
||||
private updateDropFeedback(element: HTMLElement, isDND: boolean, index?: number): void {
|
||||
const isTab = (typeof index === 'number');
|
||||
const isActiveTab = isTab && this.group.isActive(this.group.getEditor(index));
|
||||
const editor = typeof index === 'number' ? this.group.getEditor(index) : null;
|
||||
const isActiveTab = isTab && !!editor && this.group.isActive(editor);
|
||||
|
||||
// Background
|
||||
const noDNDBackgroundColor = isTab ? this.getColor(isActiveTab ? TAB_ACTIVE_BACKGROUND : TAB_INACTIVE_BACKGROUND) : null;
|
||||
@@ -728,9 +738,9 @@ export class TabsTitleControl extends TitleControl {
|
||||
// Build labels and descriptions for each editor
|
||||
const labels = this.group.editors.map(editor => ({
|
||||
editor,
|
||||
name: editor.getName(),
|
||||
description: editor.getDescription(verbosity),
|
||||
title: editor.getTitle(Verbosity.LONG)
|
||||
name: editor.getName()!,
|
||||
description: withNullAsUndefined(editor.getDescription(verbosity)),
|
||||
title: withNullAsUndefined(editor.getTitle(Verbosity.LONG))
|
||||
}));
|
||||
|
||||
// Shorten labels as needed
|
||||
@@ -782,7 +792,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
if (useLongDescriptions) {
|
||||
mapDescriptionToDuplicates.clear();
|
||||
duplicateTitles.forEach(label => {
|
||||
label.description = label.editor.getDescription(Verbosity.LONG);
|
||||
label.description = withNullAsUndefined(label.editor.getDescription(Verbosity.LONG));
|
||||
getOrSet(mapDescriptionToDuplicates, label.description, []).push(label);
|
||||
});
|
||||
}
|
||||
@@ -793,7 +803,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
|
||||
// Remove description if all descriptions are identical
|
||||
if (descriptions.length === 1) {
|
||||
for (const label of mapDescriptionToDuplicates.get(descriptions[0])) {
|
||||
for (const label of mapDescriptionToDuplicates.get(descriptions[0]) || []) {
|
||||
label.description = '';
|
||||
}
|
||||
|
||||
@@ -803,14 +813,14 @@ export class TabsTitleControl extends TitleControl {
|
||||
// Shorten descriptions
|
||||
const shortenedDescriptions = shorten(descriptions);
|
||||
descriptions.forEach((description, i) => {
|
||||
for (const label of mapDescriptionToDuplicates.get(description)) {
|
||||
for (const label of mapDescriptionToDuplicates.get(description) || []) {
|
||||
label.description = shortenedDescriptions[i];
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private getLabelConfigFlags(value: string) {
|
||||
private getLabelConfigFlags(value: string | undefined) {
|
||||
switch (value) {
|
||||
case 'short':
|
||||
return { verbosity: Verbosity.SHORT, shortenDuplicates: false };
|
||||
@@ -891,7 +901,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
tabContainer.title = title;
|
||||
|
||||
// Label
|
||||
tabLabelWidget.setResource({ name, description, resource: toResource(editor, { supportSideBySide: true }) }, { title, extraClasses: ['tab-label'], italic: !this.group.isPinned(editor) });
|
||||
tabLabelWidget.setResource({ name, description, resource: toResource(editor, { supportSideBySide: true }) || undefined }, { title, extraClasses: ['tab-label'], italic: !this.group.isPinned(editor) });
|
||||
|
||||
// {{SQL CARBON EDIT}} -- Display the editor's tab color
|
||||
const isTabActive = this.group.isActive(editor);
|
||||
@@ -961,7 +971,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
|
||||
// Highlight modified tabs with a border if configured
|
||||
if (this.accessor.partOptions.highlightModifiedTabs) {
|
||||
let modifiedBorderColor: string;
|
||||
let modifiedBorderColor: string | null;
|
||||
if (isGroupActive && isTabActive) {
|
||||
modifiedBorderColor = this.getColor(TAB_ACTIVE_MODIFIED_BORDER);
|
||||
} else if (isGroupActive && !isTabActive) {
|
||||
@@ -998,7 +1008,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
layout(dimension: Dimension): void {
|
||||
this.dimension = dimension;
|
||||
|
||||
const activeTab = this.getTab(this.group.activeEditor);
|
||||
const activeTab = this.group.activeEditor ? this.getTab(this.group.activeEditor) : undefined;
|
||||
if (!activeTab || !this.dimension) {
|
||||
return;
|
||||
}
|
||||
@@ -1015,7 +1025,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
}
|
||||
|
||||
private doLayout(dimension: Dimension): void {
|
||||
const activeTab = this.getTab(this.group.activeEditor);
|
||||
const activeTab = this.group.activeEditor ? this.getTab(this.group.activeEditor) : undefined;
|
||||
if (!activeTab) {
|
||||
return;
|
||||
}
|
||||
@@ -1050,25 +1060,25 @@ export class TabsTitleControl extends TitleControl {
|
||||
|
||||
// Reveal the active one
|
||||
const containerScrollPosX = this.tabsScrollbar.getScrollPosition().scrollLeft;
|
||||
const activeTabFits = activeTabWidth <= visibleContainerWidth;
|
||||
const activeTabFits = activeTabWidth! <= visibleContainerWidth;
|
||||
|
||||
// Tab is overflowing to the right: Scroll minimally until the element is fully visible to the right
|
||||
// Note: only try to do this if we actually have enough width to give to show the tab fully!
|
||||
if (activeTabFits && containerScrollPosX + visibleContainerWidth < activeTabPosX + activeTabWidth) {
|
||||
if (activeTabFits && containerScrollPosX + visibleContainerWidth < activeTabPosX! + activeTabWidth!) {
|
||||
this.tabsScrollbar.setScrollPosition({
|
||||
scrollLeft: containerScrollPosX + ((activeTabPosX + activeTabWidth) /* right corner of tab */ - (containerScrollPosX + visibleContainerWidth) /* right corner of view port */)
|
||||
scrollLeft: containerScrollPosX + ((activeTabPosX! + activeTabWidth!) /* right corner of tab */ - (containerScrollPosX + visibleContainerWidth) /* right corner of view port */)
|
||||
});
|
||||
}
|
||||
|
||||
// Tab is overlflowng to the left or does not fit: Scroll it into view to the left
|
||||
else if (containerScrollPosX > activeTabPosX || !activeTabFits) {
|
||||
else if (containerScrollPosX > activeTabPosX! || !activeTabFits) {
|
||||
this.tabsScrollbar.setScrollPosition({
|
||||
scrollLeft: activeTabPosX
|
||||
scrollLeft: activeTabPosX!
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private getTab(editor: IEditorInput): HTMLElement {
|
||||
private getTab(editor: IEditorInput): HTMLElement | undefined {
|
||||
const editorIndex = this.group.getIndexOfEditor(editor);
|
||||
if (editorIndex >= 0) {
|
||||
return this.tabsContainer.children[editorIndex] as HTMLElement;
|
||||
@@ -1106,17 +1116,20 @@ export class TabsTitleControl extends TitleControl {
|
||||
|
||||
// Local Editor DND
|
||||
if (this.editorTransfer.hasData(DraggedEditorIdentifier.prototype)) {
|
||||
const draggedEditor = this.editorTransfer.getData(DraggedEditorIdentifier.prototype)[0].identifier;
|
||||
const draggedEditor = this.editorTransfer.getData(DraggedEditorIdentifier.prototype)![0].identifier;
|
||||
const sourceGroup = this.accessor.getGroup(draggedEditor.groupId);
|
||||
|
||||
// Move editor to target position and index
|
||||
if (this.isMoveOperation(e, draggedEditor.groupId)) {
|
||||
sourceGroup.moveEditor(draggedEditor.editor, this.group, { index: targetIndex });
|
||||
}
|
||||
if (sourceGroup) {
|
||||
|
||||
// Copy editor to target position and index
|
||||
else {
|
||||
sourceGroup.copyEditor(draggedEditor.editor, this.group, { index: targetIndex });
|
||||
// Move editor to target position and index
|
||||
if (this.isMoveOperation(e, draggedEditor.groupId)) {
|
||||
sourceGroup.moveEditor(draggedEditor.editor, this.group, { index: targetIndex });
|
||||
}
|
||||
|
||||
// Copy editor to target position and index
|
||||
else {
|
||||
sourceGroup.copyEditor(draggedEditor.editor, this.group, { index: targetIndex });
|
||||
}
|
||||
}
|
||||
|
||||
this.group.focus();
|
||||
@@ -1125,15 +1138,17 @@ export class TabsTitleControl extends TitleControl {
|
||||
|
||||
// Local Editor Group DND
|
||||
else if (this.groupTransfer.hasData(DraggedEditorGroupIdentifier.prototype)) {
|
||||
const sourceGroup = this.accessor.getGroup(this.groupTransfer.getData(DraggedEditorGroupIdentifier.prototype)[0].identifier);
|
||||
const sourceGroup = this.accessor.getGroup(this.groupTransfer.getData(DraggedEditorGroupIdentifier.prototype)![0].identifier);
|
||||
|
||||
const mergeGroupOptions: IMergeGroupOptions = { index: targetIndex };
|
||||
if (!this.isMoveOperation(e, sourceGroup.id)) {
|
||||
mergeGroupOptions.mode = MergeGroupMode.COPY_EDITORS;
|
||||
if (sourceGroup) {
|
||||
const mergeGroupOptions: IMergeGroupOptions = { index: targetIndex };
|
||||
if (!this.isMoveOperation(e, sourceGroup.id)) {
|
||||
mergeGroupOptions.mode = MergeGroupMode.COPY_EDITORS;
|
||||
}
|
||||
|
||||
this.accessor.mergeGroup(sourceGroup, this.group, mergeGroupOptions);
|
||||
}
|
||||
|
||||
this.accessor.mergeGroup(sourceGroup, this.group, mergeGroupOptions);
|
||||
|
||||
this.group.focus();
|
||||
this.groupTransfer.clearData(DraggedEditorGroupIdentifier.prototype);
|
||||
}
|
||||
@@ -1154,7 +1169,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
// {{SQL CARBON EDIT}} -- Display the editor's tab color
|
||||
private setEditorTabColor(editor: IEditorInput, tabContainer: HTMLElement, isTabActive: boolean) {
|
||||
let sqlEditor = editor as any;
|
||||
let tabColorMode = WorkbenchUtils.getSqlConfigValue<string>(this.workspaceConfigurationService, 'tabColorMode');
|
||||
let tabColorMode = WorkbenchUtils.getSqlConfigValue<string>(this.configurationService, 'tabColorMode');
|
||||
if (tabColorMode === QueryConstants.tabColorModeOff || (tabColorMode !== QueryConstants.tabColorModeBorder && tabColorMode !== QueryConstants.tabColorModeFill)
|
||||
|| this.themeService.getTheme().type === HIGH_CONTRAST || !sqlEditor.tabColor) {
|
||||
tabContainer.style.borderTopColor = '';
|
||||
@@ -1176,7 +1191,8 @@ export class TabsTitleControl extends TitleControl {
|
||||
dispose(): void {
|
||||
super.dispose();
|
||||
|
||||
this.layoutScheduled = dispose(this.layoutScheduled);
|
||||
dispose(this.layoutScheduled);
|
||||
this.layoutScheduled = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1206,6 +1222,16 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
`);
|
||||
}
|
||||
|
||||
// High Contrast Border Color for Editor Actions
|
||||
const contrastBorderColor = theme.getColor(contrastBorder);
|
||||
if (contrastBorder) {
|
||||
collector.addRule(`
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .editor-actions {
|
||||
outline: 1px solid ${contrastBorderColor}
|
||||
}
|
||||
`);
|
||||
}
|
||||
|
||||
// Hover Background
|
||||
const tabHoverBackground = theme.getColor(TAB_HOVER_BACKGROUND);
|
||||
if (tabHoverBackground) {
|
||||
@@ -1251,12 +1277,12 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
const editorGroupHeaderTabsBackground = theme.getColor(EDITOR_GROUP_HEADER_TABS_BACKGROUND);
|
||||
const editorDragAndDropBackground = theme.getColor(EDITOR_DRAG_AND_DROP_BACKGROUND);
|
||||
|
||||
let adjustedTabBackground: Color;
|
||||
let adjustedTabBackground: Color | undefined;
|
||||
if (editorGroupHeaderTabsBackground && editorBackgroundColor) {
|
||||
adjustedTabBackground = editorGroupHeaderTabsBackground.flatten(editorBackgroundColor, editorBackgroundColor, workbenchBackground);
|
||||
}
|
||||
|
||||
let adjustedTabDragBackground: Color;
|
||||
let adjustedTabDragBackground: Color | undefined;
|
||||
if (editorGroupHeaderTabsBackground && editorBackgroundColor && editorDragAndDropBackground && editorBackgroundColor) {
|
||||
adjustedTabDragBackground = editorGroupHeaderTabsBackground.flatten(editorBackgroundColor, editorDragAndDropBackground, editorBackgroundColor, workbenchBackground);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { EditorMemento } from 'vs/workbench/browser/parts/editor/baseEditor';
|
||||
@@ -61,7 +61,7 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor {
|
||||
return new EditorMemento(this.getId(), key, Object.create(null), limit, editorGroupService); // do not persist in storage as diff editors are never persisted
|
||||
}
|
||||
|
||||
getTitle(): string {
|
||||
getTitle(): string | null {
|
||||
if (this.input) {
|
||||
return this.input.getName();
|
||||
}
|
||||
@@ -120,6 +120,7 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor {
|
||||
|
||||
// Readonly flag
|
||||
diffEditor.updateOptions({ readOnly: resolvedDiffEditorModel.isReadonly() });
|
||||
return undefined;
|
||||
}, error => {
|
||||
|
||||
// In case we tried to open a file and the response indicates that this is not a text file, fallback to binary diff.
|
||||
@@ -262,7 +263,7 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor {
|
||||
return super.loadTextEditorViewState(resource) as IDiffEditorViewState; // overridden for text diff editor support
|
||||
}
|
||||
|
||||
private saveTextDiffEditorViewState(input: EditorInput): void {
|
||||
private saveTextDiffEditorViewState(input: EditorInput | null): void {
|
||||
if (!(input instanceof DiffEditorInput)) {
|
||||
return; // only supported for diff editor inputs
|
||||
}
|
||||
@@ -288,11 +289,11 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor {
|
||||
}
|
||||
}
|
||||
|
||||
protected retrieveTextEditorViewState(resource: URI): IDiffEditorViewState {
|
||||
protected retrieveTextEditorViewState(resource: URI): IDiffEditorViewState | null {
|
||||
return this.retrieveTextDiffEditorViewState(resource); // overridden for text diff editor support
|
||||
}
|
||||
|
||||
private retrieveTextDiffEditorViewState(resource: URI): IDiffEditorViewState {
|
||||
private retrieveTextDiffEditorViewState(resource: URI): IDiffEditorViewState | null {
|
||||
const control = this.getControl();
|
||||
const model = control.getModel();
|
||||
if (!model || !model.modified || !model.original) {
|
||||
@@ -311,9 +312,9 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor {
|
||||
return control.saveViewState();
|
||||
}
|
||||
|
||||
private toDiffEditorViewStateResource(modelOrInput: IDiffEditorModel | DiffEditorInput): URI {
|
||||
let original: URI;
|
||||
let modified: URI;
|
||||
private toDiffEditorViewStateResource(modelOrInput: IDiffEditorModel | DiffEditorInput): URI | null {
|
||||
let original: URI | null;
|
||||
let modified: URI | null;
|
||||
|
||||
if (modelOrInput instanceof DiffEditorInput) {
|
||||
original = modelOrInput.originalInput.getResource();
|
||||
|
||||
@@ -20,7 +20,7 @@ import { ITextFileService, SaveReason, AutoSaveMode } from 'vs/workbench/service
|
||||
import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration';
|
||||
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
|
||||
import { isDiffEditor, isCodeEditor, ICodeEditor, getCodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { IEditorGroupsService, IEditorGroup } from 'vs/workbench/services/group/common/editorGroupsService';
|
||||
import { IEditorGroupsService, IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IWindowService } from 'vs/platform/windows/common/windows';
|
||||
|
||||
@@ -20,7 +20,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { ScrollType } from 'vs/editor/common/editorCommon';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IWindowService } from 'vs/platform/windows/common/windows';
|
||||
@@ -46,7 +46,7 @@ export class AbstractTextResourceEditor extends BaseTextEditor {
|
||||
super(id, telemetryService, instantiationService, storageService, configurationService, themeService, textFileService, editorService, editorGroupService, windowService);
|
||||
}
|
||||
|
||||
getTitle(): string {
|
||||
getTitle(): string | null {
|
||||
if (this.input) {
|
||||
return this.input.getName();
|
||||
}
|
||||
@@ -168,7 +168,7 @@ export class AbstractTextResourceEditor extends BaseTextEditor {
|
||||
super.saveState();
|
||||
}
|
||||
|
||||
private saveTextResourceEditorViewState(input: EditorInput): void {
|
||||
private saveTextResourceEditorViewState(input: EditorInput | null): void {
|
||||
if (!(input instanceof UntitledEditorInput) && !(input instanceof ResourceEditorInput)) {
|
||||
return; // only enabled for untitled and resource inputs
|
||||
}
|
||||
|
||||
@@ -32,13 +32,14 @@ import { DraggedEditorGroupIdentifier, DraggedEditorIdentifier, fillResourceData
|
||||
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
|
||||
import { BreadcrumbsConfig } from 'vs/workbench/browser/parts/editor/breadcrumbs';
|
||||
import { BreadcrumbsControl, IBreadcrumbsControlOptions } from 'vs/workbench/browser/parts/editor/breadcrumbsControl';
|
||||
import { EDITOR_TITLE_HEIGHT, IEditorGroupsAccessor, IEditorGroupView, IEditorPartOptions } from 'vs/workbench/browser/parts/editor/editor';
|
||||
import { EditorCommandsContextActionRunner, IEditorCommandsContext, IEditorInput, toResource } from 'vs/workbench/common/editor';
|
||||
import { EDITOR_TITLE_HEIGHT, IEditorGroupsAccessor, IEditorGroupView } from 'vs/workbench/browser/parts/editor/editor';
|
||||
import { EditorCommandsContextActionRunner, IEditorCommandsContext, IEditorInput, toResource, IEditorPartOptions } from 'vs/workbench/common/editor';
|
||||
import { ResourceContextKey } from 'vs/workbench/common/resources';
|
||||
import { Themable } from 'vs/workbench/common/theme';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { withUndefinedAsNull } from 'vs/base/common/types';
|
||||
|
||||
export interface IToolbarActions {
|
||||
primary: IAction[];
|
||||
@@ -50,7 +51,7 @@ export abstract class TitleControl extends Themable {
|
||||
protected readonly groupTransfer = LocalSelectionTransfer.getInstance<DraggedEditorGroupIdentifier>();
|
||||
protected readonly editorTransfer = LocalSelectionTransfer.getInstance<DraggedEditorIdentifier>();
|
||||
|
||||
protected breadcrumbsControl: BreadcrumbsControl;
|
||||
protected breadcrumbsControl?: BreadcrumbsControl;
|
||||
|
||||
private currentPrimaryEditorActionIds: string[] = [];
|
||||
private currentSecondaryEditorActionIds: string[] = [];
|
||||
@@ -155,18 +156,18 @@ export abstract class TitleControl extends Themable {
|
||||
}));
|
||||
}
|
||||
|
||||
private actionItemProvider(action: Action): IActionItem {
|
||||
private actionItemProvider(action: Action): IActionItem | null {
|
||||
const activeControl = this.group.activeControl;
|
||||
|
||||
// Check Active Editor
|
||||
let actionItem: IActionItem;
|
||||
let actionItem: IActionItem | null = null;
|
||||
if (activeControl instanceof BaseEditor) {
|
||||
actionItem = activeControl.getActionItem(action);
|
||||
}
|
||||
|
||||
// Check extensions
|
||||
if (!actionItem) {
|
||||
actionItem = createActionItem(action, this.keybindingService, this.notificationService, this.contextMenuService);
|
||||
actionItem = withUndefinedAsNull(createActionItem(action, this.keybindingService, this.notificationService, this.contextMenuService));
|
||||
}
|
||||
|
||||
return actionItem;
|
||||
@@ -218,7 +219,7 @@ export abstract class TitleControl extends Themable {
|
||||
this.editorToolBarMenuDisposables = dispose(this.editorToolBarMenuDisposables);
|
||||
|
||||
// Update the resource context
|
||||
this.resourceContext.set(toResource(this.group.activeEditor, { supportSideBySide: true }));
|
||||
this.resourceContext.set(this.group.activeEditor ? toResource(this.group.activeEditor, { supportSideBySide: true }) : null);
|
||||
|
||||
// Editor actions require the editor control to be there, so we retrieve it via service
|
||||
const activeControl = this.group.activeControl;
|
||||
@@ -254,23 +255,25 @@ export abstract class TitleControl extends Themable {
|
||||
|
||||
// Set editor group as transfer
|
||||
this.groupTransfer.setData([new DraggedEditorGroupIdentifier(this.group.id)], DraggedEditorGroupIdentifier.prototype);
|
||||
e.dataTransfer.effectAllowed = 'copyMove';
|
||||
e.dataTransfer!.effectAllowed = 'copyMove';
|
||||
|
||||
// If tabs are disabled, treat dragging as if an editor tab was dragged
|
||||
if (!this.accessor.partOptions.showTabs) {
|
||||
const resource = toResource(this.group.activeEditor, { supportSideBySide: true });
|
||||
const resource = this.group.activeEditor ? toResource(this.group.activeEditor, { supportSideBySide: true }) : null;
|
||||
if (resource) {
|
||||
this.instantiationService.invokeFunction(fillResourceDataTransfers, [resource], e);
|
||||
}
|
||||
}
|
||||
|
||||
// Drag Image
|
||||
let label = this.group.activeEditor.getName();
|
||||
if (this.accessor.partOptions.showTabs && this.group.count > 1) {
|
||||
label = localize('draggedEditorGroup', "{0} (+{1})", label, this.group.count - 1);
|
||||
}
|
||||
if (this.group.activeEditor) {
|
||||
let label = this.group.activeEditor.getName();
|
||||
if (this.accessor.partOptions.showTabs && this.group.count > 1) {
|
||||
label = localize('draggedEditorGroup', "{0} (+{1})", label, this.group.count - 1);
|
||||
}
|
||||
|
||||
applyDragImage(e, label, 'monaco-editor-group-drag-image');
|
||||
applyDragImage(e, label, 'monaco-editor-group-drag-image');
|
||||
}
|
||||
}));
|
||||
|
||||
// Drag end
|
||||
@@ -305,7 +308,7 @@ export abstract class TitleControl extends Themable {
|
||||
onHide: () => {
|
||||
|
||||
// restore previous context
|
||||
this.resourceContext.set(currentContext);
|
||||
this.resourceContext.set(currentContext || null);
|
||||
|
||||
// restore focus to active group
|
||||
this.accessor.activeGroup.focus();
|
||||
@@ -313,14 +316,14 @@ export abstract class TitleControl extends Themable {
|
||||
});
|
||||
}
|
||||
|
||||
private getKeybinding(action: IAction): ResolvedKeybinding {
|
||||
private getKeybinding(action: IAction): ResolvedKeybinding | undefined {
|
||||
return this.keybindingService.lookupKeybinding(action.id);
|
||||
}
|
||||
|
||||
protected getKeybindingLabel(action: IAction): string {
|
||||
protected getKeybindingLabel(action: IAction): string | undefined {
|
||||
const keybinding = this.getKeybinding(action);
|
||||
|
||||
return keybinding ? keybinding.getLabel() : undefined;
|
||||
return keybinding ? keybinding.getLabel() || undefined : undefined;
|
||||
}
|
||||
|
||||
abstract openEditor(editor: IEditorInput): void;
|
||||
@@ -356,7 +359,8 @@ export abstract class TitleControl extends Themable {
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.breadcrumbsControl = dispose(this.breadcrumbsControl);
|
||||
dispose(this.breadcrumbsControl);
|
||||
this.breadcrumbsControl = undefined;
|
||||
this.editorToolBarMenuDisposables = dispose(this.editorToolBarMenuDisposables);
|
||||
|
||||
super.dispose();
|
||||
|
||||
Reference in New Issue
Block a user