mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-03-31 01:00:29 -04:00
Merge VS Code 1.23.1 (#1520)
This commit is contained in:
@@ -5,7 +5,6 @@
|
||||
'use strict';
|
||||
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { Builder } from 'vs/base/browser/builder';
|
||||
import { Panel } from 'vs/workbench/browser/panel';
|
||||
import { EditorInput, EditorOptions } from 'vs/workbench/common/editor';
|
||||
import { IEditor, Position } from 'vs/platform/editor/common/editor';
|
||||
@@ -64,9 +63,9 @@ export abstract class BaseEditor extends Panel implements IEditor {
|
||||
this._options = null;
|
||||
}
|
||||
|
||||
public create(parent: Builder): void; // create is sync for editors
|
||||
public create(parent: Builder): TPromise<void>;
|
||||
public create(parent: Builder): TPromise<void> {
|
||||
public create(parent: HTMLElement): void; // create is sync for editors
|
||||
public create(parent: HTMLElement): TPromise<void>;
|
||||
public create(parent: HTMLElement): TPromise<void> {
|
||||
const res = super.create(parent);
|
||||
|
||||
// Create Editor
|
||||
@@ -76,9 +75,16 @@ export abstract class BaseEditor extends Panel implements IEditor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to create the editor in the parent builder.
|
||||
* Called to create the editor in the parent HTMLElement.
|
||||
*/
|
||||
protected abstract createEditor(parent: Builder): void;
|
||||
protected abstract createEditor(parent: HTMLElement): void;
|
||||
|
||||
/**
|
||||
* Subclasses can set this to false if it does not make sense to center editor input.
|
||||
*/
|
||||
public supportsCenteredLayout(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overload this function to allow for passing in a position argument.
|
||||
@@ -119,4 +125,4 @@ export abstract class BaseEditor extends Panel implements IEditor {
|
||||
// Super Dispose
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
import nls = require('vs/nls');
|
||||
import * as nls from 'vs/nls';
|
||||
import { BINARY_DIFF_EDITOR_ID } from 'vs/workbench/common/editor';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
|
||||
@@ -5,41 +5,51 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
import nls = require('vs/nls');
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import * as nls from 'vs/nls';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { Dimension, Builder, $ } from 'vs/base/browser/builder';
|
||||
import { EditorModel, EditorInput, EditorOptions } from 'vs/workbench/common/editor';
|
||||
import { Builder, $ } from 'vs/base/browser/builder';
|
||||
import { EditorInput, EditorOptions } from 'vs/workbench/common/editor';
|
||||
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
|
||||
import { BinaryEditorModel } from 'vs/workbench/common/editor/binaryEditorModel';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
|
||||
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { IWindowsService } from 'vs/platform/windows/common/windows';
|
||||
import { ResourceViewerContext, ResourceViewer } from 'vs/workbench/browser/parts/editor/resourceViewer';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { Dimension } from 'vs/base/browser/dom';
|
||||
|
||||
export interface IOpenCallbacks {
|
||||
openInternal: (input: EditorInput, options: EditorOptions) => void;
|
||||
openExternal: (uri: URI) => void;
|
||||
}
|
||||
|
||||
/*
|
||||
* This class is only intended to be subclassed and not instantiated.
|
||||
*/
|
||||
export abstract class BaseBinaryResourceEditor extends BaseEditor {
|
||||
private _onMetadataChanged: Emitter<void>;
|
||||
private metadata: string;
|
||||
|
||||
private readonly _onMetadataChanged: Emitter<void>;
|
||||
|
||||
private callbacks: IOpenCallbacks;
|
||||
private metadata: string;
|
||||
private binaryContainer: Builder;
|
||||
private scrollbar: DomScrollableElement;
|
||||
private resourceViewerContext: ResourceViewerContext;
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
callbacks: IOpenCallbacks,
|
||||
telemetryService: ITelemetryService,
|
||||
themeService: IThemeService,
|
||||
private windowsService: IWindowsService
|
||||
themeService: IThemeService
|
||||
) {
|
||||
super(id, telemetryService, themeService);
|
||||
|
||||
this._onMetadataChanged = new Emitter<void>();
|
||||
this.toUnbind.push(this._onMetadataChanged);
|
||||
|
||||
this.callbacks = callbacks;
|
||||
}
|
||||
|
||||
public get onMetadataChanged(): Event<void> {
|
||||
@@ -50,7 +60,7 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor {
|
||||
return this.input ? this.input.getName() : nls.localize('binaryEditor', "Binary Viewer");
|
||||
}
|
||||
|
||||
protected createEditor(parent: Builder): void {
|
||||
protected createEditor(parent: HTMLElement): void {
|
||||
|
||||
// Container for Binary
|
||||
const binaryContainerElement = document.createElement('div');
|
||||
@@ -61,7 +71,7 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor {
|
||||
|
||||
// Custom Scrollbars
|
||||
this.scrollbar = new DomScrollableElement(binaryContainerElement, { horizontal: ScrollbarVisibility.Auto, vertical: ScrollbarVisibility.Auto });
|
||||
parent.getHTMLElement().appendChild(this.scrollbar.getDomNode());
|
||||
parent.appendChild(this.scrollbar.getDomNode());
|
||||
}
|
||||
|
||||
public setInput(input: EditorInput, options?: EditorOptions): TPromise<void> {
|
||||
@@ -74,10 +84,10 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor {
|
||||
|
||||
// Otherwise set input and resolve
|
||||
return super.setInput(input, options).then(() => {
|
||||
return input.resolve(true).then((resolvedModel: EditorModel) => {
|
||||
return input.resolve(true).then(model => {
|
||||
|
||||
// Assert Model instance
|
||||
if (!(resolvedModel instanceof BinaryEditorModel)) {
|
||||
if (!(model instanceof BinaryEditorModel)) {
|
||||
return TPromise.wrapError<void>(new Error('Unable to open file as binary'));
|
||||
}
|
||||
|
||||
@@ -87,21 +97,14 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor {
|
||||
}
|
||||
|
||||
// Render Input
|
||||
const model = <BinaryEditorModel>resolvedModel;
|
||||
this.resourceViewerContext = ResourceViewer.show(
|
||||
{ name: model.getName(), resource: model.getResource(), size: model.getSize(), etag: model.getETag(), mime: model.getMime() },
|
||||
this.binaryContainer,
|
||||
this.binaryContainer.getHTMLElement(),
|
||||
this.scrollbar,
|
||||
(resource: URI) => {
|
||||
this.windowsService.openExternal(resource.toString()).then(didOpen => {
|
||||
if (!didOpen) {
|
||||
return this.windowsService.showItemInFolder(resource.fsPath);
|
||||
}
|
||||
|
||||
return void 0;
|
||||
});
|
||||
},
|
||||
(meta) => this.handleMetadataChanged(meta));
|
||||
resource => this.callbacks.openInternal(input, options),
|
||||
resource => this.callbacks.openExternal(resource),
|
||||
meta => this.handleMetadataChanged(meta)
|
||||
);
|
||||
|
||||
return TPromise.as<void>(null);
|
||||
});
|
||||
@@ -117,6 +120,10 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor {
|
||||
return this.metadata;
|
||||
}
|
||||
|
||||
public supportsCenteredLayout(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
public clearInput(): void {
|
||||
|
||||
// Clear Meta
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
'use strict';
|
||||
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import nls = require('vs/nls');
|
||||
import * as nls from 'vs/nls';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { Action, IAction } from 'vs/base/common/actions';
|
||||
import { IEditorQuickOpenEntry, IQuickOpenRegistry, Extensions as QuickOpenExtensions, QuickOpenHandlerDescriptor } from 'vs/workbench/browser/quickopen';
|
||||
@@ -225,7 +225,7 @@ registry.registerWorkbenchAction(new SyncActionDescriptor(ChangeEncodingAction,
|
||||
export class QuickOpenActionContributor extends ActionBarContributor {
|
||||
private openToSideActionInstance: OpenToSideAction;
|
||||
|
||||
constructor( @IInstantiationService private instantiationService: IInstantiationService) {
|
||||
constructor(@IInstantiationService private instantiationService: IInstantiationService) {
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
'use strict';
|
||||
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import nls = require('vs/nls');
|
||||
import * as nls from 'vs/nls';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { mixin } from 'vs/base/common/objects';
|
||||
import { getCodeEditor } from 'vs/editor/browser/services/codeEditorService';
|
||||
@@ -543,6 +543,50 @@ export class CloseEditorAction extends Action {
|
||||
}
|
||||
}
|
||||
|
||||
export class CloseOneEditorAction extends Action {
|
||||
|
||||
public static readonly ID = 'workbench.action.closeActiveEditor';
|
||||
public static readonly LABEL = nls.localize('closeOneEditor', "Close");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
|
||||
@IEditorGroupService private editorGroupService: IEditorGroupService
|
||||
) {
|
||||
super(id, label, 'close-editor-action');
|
||||
}
|
||||
|
||||
public run(context?: IEditorCommandsContext): TPromise<any> {
|
||||
const model = this.editorGroupService.getStacksModel();
|
||||
|
||||
const group = context ? model.getGroup(context.groupId) : null;
|
||||
const position = group ? model.positionOfGroup(group) : null;
|
||||
|
||||
// Close Active Editor
|
||||
if (typeof position !== 'number') {
|
||||
const activeEditor = this.editorService.getActiveEditor();
|
||||
if (activeEditor) {
|
||||
return this.editorService.closeEditor(activeEditor.position, activeEditor.input);
|
||||
}
|
||||
}
|
||||
|
||||
// Close Specific Editor
|
||||
const editor = group && context && typeof context.editorIndex === 'number' ? group.getEditor(context.editorIndex) : null;
|
||||
if (editor) {
|
||||
return this.editorService.closeEditor(position, editor);
|
||||
}
|
||||
|
||||
// Close First Editor at Position
|
||||
const visibleEditors = this.editorService.getVisibleEditors();
|
||||
if (visibleEditors[position]) {
|
||||
return this.editorService.closeEditor(position, visibleEditors[position].input);
|
||||
}
|
||||
|
||||
return TPromise.as(false);
|
||||
}
|
||||
}
|
||||
|
||||
export class RevertAndCloseEditorAction extends Action {
|
||||
|
||||
public static readonly ID = 'workbench.action.revertAndCloseActiveEditor';
|
||||
|
||||
@@ -70,7 +70,7 @@ function registerActiveEditorMoveCommand(): void {
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: EditorCommands.MoveActiveEditor,
|
||||
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
|
||||
when: EditorContextKeys.textFocus,
|
||||
when: EditorContextKeys.editorTextFocus,
|
||||
primary: null,
|
||||
handler: (accessor, args: any) => moveActiveEditor(args, accessor),
|
||||
description: {
|
||||
@@ -269,7 +269,7 @@ function registerEditorCommands() {
|
||||
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
|
||||
when: void 0,
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_U),
|
||||
handler: (accessor, resource: URI, context: IEditorCommandsContext) => {
|
||||
handler: (accessor, resource: URI | object, context: IEditorCommandsContext) => {
|
||||
const editorGroupService = accessor.get(IEditorGroupService);
|
||||
const model = editorGroupService.getStacksModel();
|
||||
const editorService = accessor.get(IWorkbenchEditorService);
|
||||
@@ -299,7 +299,7 @@ function registerEditorCommands() {
|
||||
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
|
||||
when: void 0,
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_W),
|
||||
handler: (accessor, resource: URI, context: IEditorCommandsContext) => {
|
||||
handler: (accessor, resource: URI | object, context: IEditorCommandsContext) => {
|
||||
const editorGroupService = accessor.get(IEditorGroupService);
|
||||
const editorService = accessor.get(IWorkbenchEditorService);
|
||||
const contexts = getMultiSelectedEditorContexts(context, accessor.get(IListService));
|
||||
@@ -324,7 +324,7 @@ function registerEditorCommands() {
|
||||
when: void 0,
|
||||
primary: KeyMod.CtrlCmd | KeyCode.KEY_W,
|
||||
win: { primary: KeyMod.CtrlCmd | KeyCode.F4, secondary: [KeyMod.CtrlCmd | KeyCode.KEY_W] },
|
||||
handler: (accessor, resource: URI, context: IEditorCommandsContext) => {
|
||||
handler: (accessor, resource: URI | object, context: IEditorCommandsContext) => {
|
||||
const editorGroupService = accessor.get(IEditorGroupService);
|
||||
const editorService = accessor.get(IWorkbenchEditorService);
|
||||
|
||||
@@ -373,7 +373,7 @@ function registerEditorCommands() {
|
||||
when: void 0,
|
||||
primary: void 0,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_T },
|
||||
handler: (accessor, resource: URI, context: IEditorCommandsContext) => {
|
||||
handler: (accessor, resource: URI | object, context: IEditorCommandsContext) => {
|
||||
const editorGroupService = accessor.get(IEditorGroupService);
|
||||
const editorService = accessor.get(IWorkbenchEditorService);
|
||||
const contexts = getMultiSelectedEditorContexts(context, accessor.get(IListService));
|
||||
|
||||
@@ -6,16 +6,16 @@
|
||||
'use strict';
|
||||
|
||||
import 'vs/css!./media/editorGroupsControl';
|
||||
import arrays = require('vs/base/common/arrays');
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import * as arrays from 'vs/base/common/arrays';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import types = require('vs/base/common/types');
|
||||
import { Dimension, Builder, $ } from 'vs/base/browser/builder';
|
||||
import * as types from 'vs/base/common/types';
|
||||
import { Builder, $ } from 'vs/base/browser/builder';
|
||||
import { Sash, ISashEvent, IVerticalSashLayoutProvider, IHorizontalSashLayoutProvider, Orientation } from 'vs/base/browser/ui/sash/sash';
|
||||
import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar';
|
||||
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
|
||||
import DOM = require('vs/base/browser/dom');
|
||||
import errors = require('vs/base/common/errors');
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
import { isMacintosh } from 'vs/base/common/platform';
|
||||
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
@@ -29,7 +29,7 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag
|
||||
import { TabsTitleControl } from 'vs/workbench/browser/parts/editor/tabsTitleControl';
|
||||
import { ITitleAreaControl } from 'vs/workbench/browser/parts/editor/titleControl';
|
||||
import { NoTabsTitleControl } from 'vs/workbench/browser/parts/editor/noTabsTitleControl';
|
||||
import { IEditorStacksModel, IStacksModelChangeEvent, IEditorGroup, EditorOptions, TextEditorOptions, IEditorIdentifier, EditorInput, PREFERENCES_EDITOR_ID, TEXT_DIFF_EDITOR_ID } from 'vs/workbench/common/editor';
|
||||
import { IEditorStacksModel, IStacksModelChangeEvent, IEditorGroup, EditorOptions, TextEditorOptions, IEditorIdentifier, EditorInput } from 'vs/workbench/common/editor';
|
||||
import { getCodeEditor } from 'vs/editor/browser/services/codeEditorService';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { editorBackground, contrastBorder, activeContrastBorder } from 'vs/platform/theme/common/colorRegistry';
|
||||
@@ -40,6 +40,7 @@ import { ResourcesDropHandler, LocalSelectionTransfer, DraggedEditorIdentifier }
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IPartService } from 'vs/workbench/services/part/common/partService';
|
||||
|
||||
|
||||
export enum Rochade {
|
||||
NONE,
|
||||
TWO_TO_ONE,
|
||||
@@ -74,7 +75,7 @@ export interface IEditorGroupsControl {
|
||||
updateProgress(position: Position, state: ProgressState): void;
|
||||
updateTitleAreas(refreshActive?: boolean): void;
|
||||
|
||||
layout(dimension: Dimension): void;
|
||||
layout(dimension: DOM.Dimension): void;
|
||||
layout(position: Position): void;
|
||||
|
||||
arrangeGroups(arrangement: GroupArrangement): void;
|
||||
@@ -121,8 +122,8 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
|
||||
|
||||
private stacks: IEditorStacksModel;
|
||||
|
||||
private parent: Builder;
|
||||
private dimension: Dimension;
|
||||
private parent: HTMLElement;
|
||||
private dimension: DOM.Dimension;
|
||||
private dragging: boolean;
|
||||
|
||||
private layoutVertically: boolean;
|
||||
@@ -151,7 +152,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
|
||||
private centeredEditorActive: boolean;
|
||||
private centeredEditorSashLeft: Sash;
|
||||
private centeredEditorSashRight: Sash;
|
||||
private centeredEditorPreferedSize: number;
|
||||
private centeredEditorPreferredSize: number;
|
||||
private centeredEditorLeftMarginRatio: number;
|
||||
private centeredEditorDragStartPosition: number;
|
||||
private centeredEditorDragStartSize: number;
|
||||
@@ -163,7 +164,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
|
||||
|
||||
private visibleEditorFocusTrackerDisposable: IDisposable[];
|
||||
|
||||
private _onGroupFocusChanged: Emitter<void>;
|
||||
private readonly _onGroupFocusChanged: Emitter<void>;
|
||||
|
||||
private onStacksChangeScheduler: RunOnceScheduler;
|
||||
private stacksChangedBuffer: IStacksModelChangeEvent[];
|
||||
@@ -171,12 +172,12 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
|
||||
private transfer = LocalSelectionTransfer.getInstance<DraggedEditorIdentifier>();
|
||||
|
||||
constructor(
|
||||
parent: Builder,
|
||||
parent: HTMLElement,
|
||||
groupOrientation: GroupOrientation,
|
||||
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
|
||||
@IEditorGroupService private editorGroupService: IEditorGroupService,
|
||||
@IPartService private partService: IPartService,
|
||||
@IStorageService private storageServise: IStorageService,
|
||||
@IStorageService private storageService: IStorageService,
|
||||
@IContextKeyService private contextKeyService: IContextKeyService,
|
||||
@IExtensionService private extensionService: IExtensionService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@@ -188,7 +189,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
|
||||
this.stacks = editorGroupService.getStacksModel();
|
||||
|
||||
this.parent = parent;
|
||||
this.dimension = new Dimension(0, 0);
|
||||
this.dimension = new DOM.Dimension(0, 0);
|
||||
|
||||
this.silos = [];
|
||||
this.silosSize = [];
|
||||
@@ -291,6 +292,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
|
||||
titleControl.dispose();
|
||||
titleContainer.empty();
|
||||
this.createTitleControl(this.stacks.groupAt(position), this.silos[position], titleContainer, this.getInstantiationService(position));
|
||||
this.layoutTitleControl(position);
|
||||
}
|
||||
|
||||
// Refresh title when layout options change
|
||||
@@ -369,8 +371,8 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
|
||||
this.trackFocus(editor, position);
|
||||
|
||||
// Find target container and build into
|
||||
const target = this.silos[position].child();
|
||||
editor.getContainer().build(target);
|
||||
const target = this.silos[position].child().getHTMLElement();
|
||||
target.appendChild(editor.getContainer());
|
||||
|
||||
// Adjust layout according to provided ratios (used when restoring multiple editors at once)
|
||||
if (ratio && (ratio.length === 2 || ratio.length === 3)) {
|
||||
@@ -442,7 +444,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
|
||||
}
|
||||
|
||||
// Show editor container
|
||||
editor.getContainer().show();
|
||||
DOM.show(editor.getContainer());
|
||||
}
|
||||
|
||||
private getVisibleEditorCount(): number {
|
||||
@@ -554,7 +556,11 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
|
||||
this.clearPosition(position);
|
||||
|
||||
// Take editor container offdom and hide
|
||||
editor.getContainer().offDOM().hide();
|
||||
const editorContainer = editor.getContainer();
|
||||
if (editorContainer.parentNode) {
|
||||
editorContainer.parentNode.removeChild(editorContainer);
|
||||
}
|
||||
DOM.hide(editorContainer);
|
||||
|
||||
// Adjust layout and rochade if instructed to do so
|
||||
if (layoutAndRochade) {
|
||||
@@ -780,10 +786,10 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
|
||||
this.layoutVertically = (orientation !== 'horizontal');
|
||||
|
||||
// Editor Layout
|
||||
const verticalLayouting = this.parent.hasClass('vertical-layout');
|
||||
const verticalLayouting = DOM.hasClass(this.parent, 'vertical-layout');
|
||||
if (verticalLayouting !== this.layoutVertically) {
|
||||
this.parent.removeClass('vertical-layout', 'horizontal-layout');
|
||||
this.parent.addClass(this.layoutVertically ? 'vertical-layout' : 'horizontal-layout');
|
||||
DOM.removeClasses(this.parent, 'vertical-layout', 'horizontal-layout');
|
||||
DOM.addClass(this.parent, this.layoutVertically ? 'vertical-layout' : 'horizontal-layout');
|
||||
|
||||
this.sashOne.setOrientation(this.layoutVertically ? Orientation.VERTICAL : Orientation.HORIZONTAL);
|
||||
this.sashTwo.setOrientation(this.layoutVertically ? Orientation.VERTICAL : Orientation.HORIZONTAL);
|
||||
@@ -968,16 +974,16 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
|
||||
private create(): void {
|
||||
|
||||
// Store layout as class property
|
||||
this.parent.addClass(this.layoutVertically ? 'vertical-layout' : 'horizontal-layout');
|
||||
DOM.addClass(this.parent, this.layoutVertically ? 'vertical-layout' : 'horizontal-layout');
|
||||
|
||||
// Allow to drop into container to open
|
||||
this.enableDropTarget(this.parent.getHTMLElement());
|
||||
this.enableDropTarget(this.parent);
|
||||
|
||||
// Silo One
|
||||
this.silos[Position.ONE] = $(this.parent).div({ class: 'one-editor-silo editor-one' });
|
||||
|
||||
// Sash One
|
||||
this.sashOne = new Sash(this.parent.getHTMLElement(), this, { baseSize: 5, orientation: this.layoutVertically ? Orientation.VERTICAL : Orientation.HORIZONTAL });
|
||||
this.sashOne = new Sash(this.parent, this, { baseSize: 5, orientation: this.layoutVertically ? Orientation.VERTICAL : Orientation.HORIZONTAL });
|
||||
this.toUnbind.push(this.sashOne.onDidStart(() => this.onSashOneDragStart()));
|
||||
this.toUnbind.push(this.sashOne.onDidChange((e: ISashEvent) => this.onSashOneDrag(e)));
|
||||
this.toUnbind.push(this.sashOne.onDidEnd(() => this.onSashOneDragEnd()));
|
||||
@@ -988,7 +994,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
|
||||
this.silos[Position.TWO] = $(this.parent).div({ class: 'one-editor-silo editor-two' });
|
||||
|
||||
// Sash Two
|
||||
this.sashTwo = new Sash(this.parent.getHTMLElement(), this, { baseSize: 5, orientation: this.layoutVertically ? Orientation.VERTICAL : Orientation.HORIZONTAL });
|
||||
this.sashTwo = new Sash(this.parent, this, { baseSize: 5, orientation: this.layoutVertically ? Orientation.VERTICAL : Orientation.HORIZONTAL });
|
||||
this.toUnbind.push(this.sashTwo.onDidStart(() => this.onSashTwoDragStart()));
|
||||
this.toUnbind.push(this.sashTwo.onDidChange((e: ISashEvent) => this.onSashTwoDrag(e)));
|
||||
this.toUnbind.push(this.sashTwo.onDidEnd(() => this.onSashTwoDragEnd()));
|
||||
@@ -1033,9 +1039,9 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
|
||||
this.createTitleControl(this.stacks.groupAt(position), silo, titleContainer, instantiationService);
|
||||
|
||||
// Progress Bar
|
||||
const progressBar = new ProgressBar($(container));
|
||||
const progressBar = new ProgressBar(container.getHTMLElement());
|
||||
this.toUnbind.push(attachProgressBarStyler(progressBar, this.themeService));
|
||||
progressBar.getContainer().hide();
|
||||
progressBar.hide();
|
||||
container.setProperty(EditorGroupsControl.PROGRESS_BAR_CONTROL_KEY, progressBar); // associate with container
|
||||
|
||||
// Sash for first position to support centered editor layout
|
||||
@@ -1059,11 +1065,11 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
|
||||
this.centeredEditorLeftMarginRatio = 0.5;
|
||||
|
||||
// Restore centered layout position and size
|
||||
const centeredLayoutDataString = this.storageServise.get(EditorGroupsControl.CENTERED_EDITOR_LAYOUT_DATA_STORAGE_KEY, StorageScope.GLOBAL);
|
||||
const centeredLayoutDataString = this.storageService.get(EditorGroupsControl.CENTERED_EDITOR_LAYOUT_DATA_STORAGE_KEY, StorageScope.GLOBAL);
|
||||
if (centeredLayoutDataString) {
|
||||
const centeredLayout = <CenteredEditorLayoutData>JSON.parse(centeredLayoutDataString);
|
||||
this.centeredEditorLeftMarginRatio = centeredLayout.leftMarginRatio;
|
||||
this.centeredEditorPreferedSize = centeredLayout.size;
|
||||
this.centeredEditorPreferredSize = centeredLayout.size;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1284,7 +1290,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
|
||||
if (!overlay) {
|
||||
const containers = $this.visibleEditors.filter(e => !!e).map(e => e.getContainer());
|
||||
containers.forEach((container, index) => {
|
||||
if (container && DOM.isAncestor(target, container.getHTMLElement())) {
|
||||
if (container && DOM.isAncestor(target, container)) {
|
||||
const activeContrastBorderColor = $this.getColor(activeContrastBorder);
|
||||
overlay = $('div').style({
|
||||
top: $this.tabOptions.showTabs ? `${EditorGroupsControl.EDITOR_TITLE_HEIGHT}px` : 0,
|
||||
@@ -1596,8 +1602,8 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
|
||||
// TODO@Ben remove me after a while
|
||||
/* __GDPR__
|
||||
"editorGroupMoved" : {
|
||||
"source" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"to": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
"source" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
|
||||
"to": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }
|
||||
}
|
||||
*/
|
||||
this.telemetryService.publicLog('editorGroupMoved', { source: position, to: moveTo });
|
||||
@@ -1627,11 +1633,11 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
|
||||
|
||||
let borderColor = null;
|
||||
if (isDragging) {
|
||||
this.parent.addClass('dragging');
|
||||
DOM.addClass(this.parent, 'dragging');
|
||||
silo.addClass('dragging');
|
||||
borderColor = this.getColor(EDITOR_GROUP_BORDER) || this.getColor(contrastBorder);
|
||||
} else {
|
||||
this.parent.removeClass('dragging');
|
||||
DOM.removeClass(this.parent, 'dragging');
|
||||
silo.removeClass('dragging');
|
||||
}
|
||||
|
||||
@@ -1930,11 +1936,11 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
|
||||
}
|
||||
|
||||
private get centeredEditorAvailableSize(): number {
|
||||
return this.silosSize[Position.ONE] - EditorGroupsControl.CENTERED_EDITOR_MIN_MARGIN * 2;
|
||||
return this.dimension.width - EditorGroupsControl.CENTERED_EDITOR_MIN_MARGIN * 2;
|
||||
}
|
||||
|
||||
private get centeredEditorSize(): number {
|
||||
return Math.min(this.centeredEditorAvailableSize, this.centeredEditorPreferedSize);
|
||||
return Math.min(this.centeredEditorAvailableSize, this.centeredEditorPreferredSize);
|
||||
}
|
||||
|
||||
private get centeredEditorPosition(): number {
|
||||
@@ -1956,7 +1962,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
|
||||
}
|
||||
|
||||
if (size > 3 * this.minSize && size < this.centeredEditorAvailableSize) {
|
||||
this.centeredEditorPreferedSize = size;
|
||||
this.centeredEditorPreferredSize = size;
|
||||
position -= EditorGroupsControl.CENTERED_EDITOR_MIN_MARGIN;
|
||||
position = Math.min(position, this.centeredEditorAvailableSize - this.centeredEditorSize);
|
||||
position = Math.max(0, position);
|
||||
@@ -1971,7 +1977,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
|
||||
leftMarginRatio: this.centeredEditorLeftMarginRatio,
|
||||
size: this.centeredEditorSize
|
||||
};
|
||||
this.storageServise.store(EditorGroupsControl.CENTERED_EDITOR_LAYOUT_DATA_STORAGE_KEY, JSON.stringify(data), StorageScope.GLOBAL);
|
||||
this.storageService.store(EditorGroupsControl.CENTERED_EDITOR_LAYOUT_DATA_STORAGE_KEY, JSON.stringify(data), StorageScope.GLOBAL);
|
||||
}
|
||||
|
||||
public getVerticalSashTop(sash: Sash): number {
|
||||
@@ -2013,17 +2019,17 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
|
||||
return this.dragging;
|
||||
}
|
||||
|
||||
public layout(dimension: Dimension): void;
|
||||
public layout(dimension: DOM.Dimension): void;
|
||||
public layout(position: Position): void;
|
||||
public layout(arg: any): void {
|
||||
if (arg instanceof Dimension) {
|
||||
this.layoutControl(<Dimension>arg);
|
||||
if (arg instanceof DOM.Dimension) {
|
||||
this.layoutControl(<DOM.Dimension>arg);
|
||||
} else {
|
||||
this.layoutEditor(<Position>arg);
|
||||
}
|
||||
}
|
||||
|
||||
private layoutControl(dimension: Dimension): void {
|
||||
private layoutControl(dimension: DOM.Dimension): void {
|
||||
let oldDimension = this.dimension;
|
||||
this.dimension = dimension;
|
||||
|
||||
@@ -2141,14 +2147,14 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
|
||||
});
|
||||
|
||||
// Layout centered Editor (only in vertical layout when one group is opened)
|
||||
const id = this.visibleEditors[Position.ONE] ? this.visibleEditors[Position.ONE].getId() : undefined;
|
||||
const doCentering = this.layoutVertically && this.stacks.groups.length === 1 && this.partService.isEditorLayoutCentered() && id !== PREFERENCES_EDITOR_ID && id !== TEXT_DIFF_EDITOR_ID;
|
||||
const doCentering = this.partService.isEditorLayoutCentered() && this.stacks.groups.length === 1 &&
|
||||
this.visibleEditors[Position.ONE] && this.visibleEditors[Position.ONE].supportsCenteredLayout();
|
||||
if (doCentering && !this.centeredEditorActive) {
|
||||
this.centeredEditorSashLeft.show();
|
||||
this.centeredEditorSashRight.show();
|
||||
|
||||
// no size set yet. Calculate a default value
|
||||
if (!this.centeredEditorPreferedSize) {
|
||||
if (!this.centeredEditorPreferredSize) {
|
||||
this.resetCenteredEditor(false);
|
||||
}
|
||||
} else if (!doCentering && this.centeredEditorActive) {
|
||||
@@ -2169,16 +2175,18 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
|
||||
});
|
||||
|
||||
// Layout title controls
|
||||
POSITIONS.forEach(position => {
|
||||
const siloWidth = this.layoutVertically ? this.silosSize[position] : this.dimension.width;
|
||||
|
||||
this.getTitleAreaControl(position).layout(new Dimension(siloWidth, EditorGroupsControl.EDITOR_TITLE_HEIGHT));
|
||||
});
|
||||
POSITIONS.forEach(position => this.layoutTitleControl(position));
|
||||
|
||||
// Update minimized state
|
||||
this.updateMinimizedState();
|
||||
}
|
||||
|
||||
private layoutTitleControl(position: Position): void {
|
||||
const siloWidth = this.layoutVertically ? this.silosSize[position] : this.dimension.width;
|
||||
|
||||
this.getTitleAreaControl(position).layout(new DOM.Dimension(siloWidth, EditorGroupsControl.EDITOR_TITLE_HEIGHT));
|
||||
}
|
||||
|
||||
private layoutEditor(position: Position): void {
|
||||
const editorSize = this.silosSize[position];
|
||||
const editor = this.visibleEditors[position];
|
||||
@@ -2201,20 +2209,20 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
|
||||
}
|
||||
|
||||
const editorContainer = editor.getContainer();
|
||||
editorContainer.style('margin-left', this.centeredEditorActive ? `${editorPosition}px` : null);
|
||||
editorContainer.style('width', this.centeredEditorActive ? `${editorWidth}px` : null);
|
||||
editorContainer.style('border-color', this.centeredEditorActive ? this.getColor(EDITOR_GROUP_BORDER) || this.getColor(contrastBorder) : null);
|
||||
editor.layout(new Dimension(editorWidth, editorHeight));
|
||||
editorContainer.style.marginLeft = this.centeredEditorActive ? `${editorPosition}px` : null;
|
||||
editorContainer.style.width = this.centeredEditorActive ? `${editorWidth}px` : null;
|
||||
editorContainer.style.borderColor = this.centeredEditorActive ? this.getColor(EDITOR_GROUP_BORDER) || this.getColor(contrastBorder) : null;
|
||||
editor.layout(new DOM.Dimension(editorWidth, editorHeight));
|
||||
}
|
||||
}
|
||||
|
||||
private resetCenteredEditor(layout: boolean = true) {
|
||||
this.centeredEditorLeftMarginRatio = 0.5;
|
||||
this.centeredEditorPreferedSize = Math.floor(this.dimension.width * EditorGroupsControl.GOLDEN_RATIO);
|
||||
this.centeredEditorPreferredSize = Math.floor(this.dimension.width * EditorGroupsControl.GOLDEN_RATIO);
|
||||
if (layout) {
|
||||
this.layoutContainers();
|
||||
}
|
||||
this.storageServise.remove(EditorGroupsControl.CENTERED_EDITOR_LAYOUT_DATA_STORAGE_KEY, StorageScope.GLOBAL);
|
||||
this.storageService.remove(EditorGroupsControl.CENTERED_EDITOR_LAYOUT_DATA_STORAGE_KEY, StorageScope.GLOBAL);
|
||||
}
|
||||
|
||||
public getInstantiationService(position: Position): IInstantiationService {
|
||||
@@ -2269,13 +2277,13 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
|
||||
|
||||
switch (state) {
|
||||
case ProgressState.INFINITE:
|
||||
progressbar.infinite().getContainer().show();
|
||||
progressbar.infinite().show();
|
||||
break;
|
||||
case ProgressState.DONE:
|
||||
progressbar.done().getContainer().hide();
|
||||
progressbar.done().hide();
|
||||
break;
|
||||
case ProgressState.STOP:
|
||||
progressbar.stop().getContainer().hide();
|
||||
progressbar.stop().hide();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,12 +9,11 @@ import 'vs/css!./media/editorpart';
|
||||
import 'vs/workbench/browser/parts/editor/editor.contribution';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { Dimension, Builder, $ } from 'vs/base/browser/builder';
|
||||
import nls = require('vs/nls');
|
||||
import strings = require('vs/base/common/strings');
|
||||
import arrays = require('vs/base/common/arrays');
|
||||
import types = require('vs/base/common/types');
|
||||
import errors = require('vs/base/common/errors');
|
||||
import * as nls from 'vs/nls';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import * as arrays from 'vs/base/common/arrays';
|
||||
import * as types from 'vs/base/common/types';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
import { getCodeEditor } from 'vs/editor/browser/services/codeEditorService';
|
||||
import { toErrorMessage } from 'vs/base/common/errorMessage';
|
||||
@@ -35,20 +34,19 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IProgressService } from 'vs/platform/progress/common/progress';
|
||||
import { EditorStacksModel, EditorGroup, EditorIdentifier, EditorCloseEvent } from 'vs/workbench/common/editor/editorStacksModel';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { Event, Emitter, once } from 'vs/base/common/event';
|
||||
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { editorBackground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { EDITOR_GROUP_BACKGROUND } from 'vs/workbench/common/theme';
|
||||
import { createCSSRule } from 'vs/base/browser/dom';
|
||||
import { createCSSRule, Dimension, addClass, removeClass } from 'vs/base/browser/dom';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { join } from 'vs/base/common/paths';
|
||||
import { IEditorDescriptor, IEditorRegistry, Extensions as EditorExtensions } from 'vs/workbench/browser/editor';
|
||||
import { ThrottledEmitter } from 'vs/base/common/async';
|
||||
import { isCodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { isUndefinedOrNull } from 'vs/base/common/types';
|
||||
import { INotificationService, Severity, INotificationActions } from 'vs/platform/notification/common/notification';
|
||||
import { isErrorWithActions } from 'vs/base/common/errors';
|
||||
import { dispose } from 'vs/base/common/lifecycle';
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
import { convertEditorInput } from 'sql/parts/common/customInputConverter';
|
||||
@@ -107,16 +105,17 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService
|
||||
private forceHideTabs: boolean;
|
||||
private doNotFireTabOptionsChanged: boolean;
|
||||
private revealIfOpen: boolean;
|
||||
|
||||
private _onEditorsChanged: ThrottledEmitter<void>;
|
||||
private _onEditorOpening: Emitter<IEditorOpeningEvent>;
|
||||
private _onEditorGroupMoved: Emitter<void>;
|
||||
private _onEditorOpenFail: Emitter<EditorInput>;
|
||||
private _onGroupOrientationChanged: Emitter<void>;
|
||||
private _onTabOptionsChanged: Emitter<IEditorTabOptions>;
|
||||
|
||||
private ignoreOpenEditorErrors: boolean;
|
||||
private textCompareEditorVisible: IContextKey<boolean>;
|
||||
|
||||
private readonly _onEditorsChanged: ThrottledEmitter<void>;
|
||||
private readonly _onEditorOpening: Emitter<IEditorOpeningEvent>;
|
||||
private readonly _onEditorGroupMoved: Emitter<void>;
|
||||
private readonly _onEditorOpenFail: Emitter<EditorInput>;
|
||||
private readonly _onGroupOrientationChanged: Emitter<void>;
|
||||
private readonly _onTabOptionsChanged: Emitter<IEditorTabOptions>;
|
||||
private readonly _onLayout: Emitter<Dimension>;
|
||||
|
||||
// The following data structures are partitioned into array of Position as provided by Services.POSITION array
|
||||
private visibleEditors: BaseEditor[];
|
||||
private instantiatedEditors: BaseEditor[][];
|
||||
@@ -124,9 +123,6 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService
|
||||
private pendingEditorInputsToClose: EditorIdentifier[];
|
||||
private pendingEditorInputCloseTimeout: number;
|
||||
|
||||
private onLayoutEmitter = new Emitter<Dimension>();
|
||||
public onLayout = this.onLayoutEmitter.event;
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
restoreFromStorage: boolean,
|
||||
@@ -148,6 +144,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService
|
||||
this._onEditorOpenFail = new Emitter<EditorInput>();
|
||||
this._onGroupOrientationChanged = new Emitter<void>();
|
||||
this._onTabOptionsChanged = new Emitter<IEditorTabOptions>();
|
||||
this._onLayout = new Emitter<Dimension>();
|
||||
|
||||
this.visibleEditors = [];
|
||||
|
||||
@@ -298,6 +295,10 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService
|
||||
this.editorGroupsControl.resizeGroup(position, groupSizeChange);
|
||||
}
|
||||
|
||||
public get onLayout(): Event<Dimension> {
|
||||
return this._onLayout.event;
|
||||
}
|
||||
|
||||
public get onEditorsChanged(): Event<void> {
|
||||
return this._onEditorsChanged.event;
|
||||
}
|
||||
@@ -479,11 +480,12 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService
|
||||
|
||||
// Create editor as needed
|
||||
if (!editor.getContainer()) {
|
||||
editor.create($().div({
|
||||
'class': 'editor-container',
|
||||
'role': 'tabpanel',
|
||||
id: descriptor.getId()
|
||||
}));
|
||||
const editorContainer = document.createElement('div');
|
||||
editorContainer.id = descriptor.getId();
|
||||
addClass(editorContainer, 'editor-container');
|
||||
editorContainer.setAttribute('role', 'tabpanel');
|
||||
|
||||
editor.create(editorContainer);
|
||||
}
|
||||
|
||||
return editor;
|
||||
@@ -555,18 +557,21 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService
|
||||
// Stop loading promise if any
|
||||
monitor.cancel();
|
||||
|
||||
// Report error only if this was not us restoring previous error state
|
||||
if (this.partService.isCreated() && !errors.isPromiseCanceledError(error)) {
|
||||
// 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.partService.isCreated() && !errors.isPromiseCanceledError(error) && !this.ignoreOpenEditorErrors) {
|
||||
const actions: INotificationActions = { primary: [] };
|
||||
if (isErrorWithActions(error)) {
|
||||
actions.primary = error.actions;
|
||||
if (errors.isErrorWithActions(error)) {
|
||||
actions.primary = (error as errors.IErrorWithActions).actions;
|
||||
}
|
||||
|
||||
this.notificationService.notify({
|
||||
const handle = this.notificationService.notify({
|
||||
severity: Severity.Error,
|
||||
message: nls.localize('editorOpenError', "Unable to open '{0}': {1}.", input.getName(), toErrorMessage(error)),
|
||||
actions
|
||||
});
|
||||
|
||||
once(handle.onDidClose)(() => dispose(actions.primary));
|
||||
}
|
||||
|
||||
this.editorGroupsControl.updateProgress(position, ProgressState.DONE);
|
||||
@@ -576,7 +581,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService
|
||||
|
||||
// Recover by closing the active editor (if the input is still the active one)
|
||||
if (group.activeEditor === input) {
|
||||
this.doCloseActiveEditor(group, !(options && options.preserveFocus) /* still preserve focus as needed */);
|
||||
this.doCloseActiveEditor(group, !(options && options.preserveFocus) /* still preserve focus as needed */, true /* from error */);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -610,7 +615,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService
|
||||
}
|
||||
}
|
||||
|
||||
private doCloseActiveEditor(group: EditorGroup, focusNext = true): void {
|
||||
private doCloseActiveEditor(group: EditorGroup, focusNext = true, fromError?: boolean): void {
|
||||
const position = this.stacks.positionOfGroup(group);
|
||||
|
||||
// Update stacks model
|
||||
@@ -623,7 +628,22 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService
|
||||
|
||||
// Otherwise open next active
|
||||
else {
|
||||
this.openEditor(group.activeEditor, !focusNext ? EditorOptions.create({ preserveFocus: true }) : null, position).done(null, errors.onUnexpectedError);
|
||||
// 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.
|
||||
if (fromError) {
|
||||
this.ignoreOpenEditorErrors = true;
|
||||
}
|
||||
|
||||
this.openEditor(group.activeEditor, !focusNext ? EditorOptions.create({ preserveFocus: true }) : null, position).done(() => {
|
||||
this.ignoreOpenEditorErrors = false;
|
||||
}, error => {
|
||||
errors.onUnexpectedError(error);
|
||||
|
||||
this.ignoreOpenEditorErrors = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -710,7 +730,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService
|
||||
}
|
||||
|
||||
// Then check for array of positions to close
|
||||
if (Array.isArray(positionsOrEditors) || isUndefinedOrNull(positionsOrEditors)) {
|
||||
if (Array.isArray(positionsOrEditors) || types.isUndefinedOrNull(positionsOrEditors)) {
|
||||
return this.doCloseAllEditorsAtPositions(positionsOrEditors as Position[]);
|
||||
}
|
||||
|
||||
@@ -833,16 +853,18 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService
|
||||
|
||||
// Close: By Filter or all
|
||||
else {
|
||||
editorsToClose = group.getEditors(true /* in MRU order */);
|
||||
filter = filterOrEditors || Object.create(null);
|
||||
|
||||
const hasDirection = !types.isUndefinedOrNull(filter.direction);
|
||||
editorsToClose = group.getEditors(!hasDirection /* in MRU order only if direction is not specified */);
|
||||
|
||||
// Filter: saved only
|
||||
if (filter.savedOnly) {
|
||||
editorsToClose = editorsToClose.filter(e => !e.isDirty());
|
||||
}
|
||||
|
||||
// Filter: direction (left / right)
|
||||
else if (!types.isUndefinedOrNull(filter.direction)) {
|
||||
else if (hasDirection) {
|
||||
editorsToClose = (filter.direction === Direction.LEFT) ? editorsToClose.slice(0, group.indexOf(filter.except)) : editorsToClose.slice(group.indexOf(filter.except) + 1);
|
||||
}
|
||||
|
||||
@@ -1141,12 +1163,12 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService
|
||||
return this.editorGroupsControl.getGroupOrientation();
|
||||
}
|
||||
|
||||
public createContentArea(parent: Builder): Builder {
|
||||
public createContentArea(parent: HTMLElement): HTMLElement {
|
||||
|
||||
// Content Container
|
||||
const contentArea = $(parent)
|
||||
.div()
|
||||
.addClass('content');
|
||||
const contentArea = document.createElement('div');
|
||||
addClass(contentArea, 'content');
|
||||
parent.appendChild(contentArea);
|
||||
|
||||
// get settings
|
||||
this.memento = this.getMemento(this.storageService, MementoScope.WORKSPACE);
|
||||
@@ -1164,19 +1186,19 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService
|
||||
|
||||
// Part container
|
||||
const container = this.getContainer();
|
||||
container.style('background-color', this.getColor(editorBackground));
|
||||
container.style.backgroundColor = this.getColor(editorBackground);
|
||||
|
||||
// Content area
|
||||
const content = this.getContentArea();
|
||||
|
||||
const groupCount = this.stacks.groups.length;
|
||||
if (groupCount > 1) {
|
||||
content.addClass('multiple-groups');
|
||||
addClass(content, 'multiple-groups');
|
||||
} else {
|
||||
content.removeClass('multiple-groups');
|
||||
removeClass(content, 'multiple-groups');
|
||||
}
|
||||
|
||||
content.style('background-color', groupCount > 0 ? this.getColor(EDITOR_GROUP_BACKGROUND) : null);
|
||||
content.style.backgroundColor = groupCount > 0 ? this.getColor(EDITOR_GROUP_BACKGROUND) : null;
|
||||
}
|
||||
|
||||
private onGroupFocusChanged(): void {
|
||||
@@ -1474,7 +1496,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService
|
||||
this.dimension = sizes[1];
|
||||
this.editorGroupsControl.layout(this.dimension);
|
||||
|
||||
this.onLayoutEmitter.fire(dimension);
|
||||
this._onLayout.fire(dimension);
|
||||
|
||||
return sizes;
|
||||
}
|
||||
@@ -1512,6 +1534,9 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService
|
||||
this._onEditorOpening.dispose();
|
||||
this._onEditorGroupMoved.dispose();
|
||||
this._onEditorOpenFail.dispose();
|
||||
this._onGroupOrientationChanged.dispose();
|
||||
this._onTabOptionsChanged.dispose();
|
||||
this._onLayout.dispose();
|
||||
|
||||
// Reset Tokens
|
||||
this.editorOpenToken = [];
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
|
||||
import 'vs/css!./media/editorpicker';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import nls = require('vs/nls');
|
||||
import * as nls from 'vs/nls';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import errors = require('vs/base/common/errors');
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
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';
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
'use strict';
|
||||
|
||||
import 'vs/css!./media/editorstatus';
|
||||
import nls = require('vs/nls');
|
||||
import * as nls from 'vs/nls';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { $, append, runAtThisOrScheduleAtNextAnimationFrame, addDisposableListener } from 'vs/base/browser/dom';
|
||||
import strings = require('vs/base/common/strings');
|
||||
import paths = require('vs/base/common/paths');
|
||||
import types = require('vs/base/common/types');
|
||||
import { $, append, runAtThisOrScheduleAtNextAnimationFrame, addDisposableListener, getDomNodePagePosition } from 'vs/base/browser/dom';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import * as paths from 'vs/base/common/paths';
|
||||
import * as types from 'vs/base/common/types';
|
||||
import uri from 'vs/base/common/uri';
|
||||
import errors = require('vs/base/common/errors');
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
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';
|
||||
@@ -50,35 +50,58 @@ import { IConfigurationChangedEvent, IEditorOptions } from 'vs/editor/common/con
|
||||
import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { attachStylerCallback, attachButtonStyler } from 'vs/platform/theme/common/styler';
|
||||
import { widgetShadow, editorWidgetBackground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { attachButtonStyler } from 'vs/platform/theme/common/styler';
|
||||
import { widgetShadow, editorWidgetBackground, foreground, darken, contrastBorder } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
import { deepClone } from 'vs/base/common/objects';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { Button } from 'vs/base/browser/ui/button/button';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { IAnchor } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { Themable } from 'vs/workbench/common/theme';
|
||||
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
|
||||
|
||||
// TODO@Sandeep layer breaker
|
||||
// tslint:disable-next-line:import-patterns
|
||||
import { IPreferencesService } from 'vs/workbench/parts/preferences/common/preferences';
|
||||
class SideBySideEditorEncodingSupport implements IEncodingSupport {
|
||||
constructor(private master: IEncodingSupport, private details: IEncodingSupport) { }
|
||||
|
||||
public getEncoding(): string {
|
||||
return this.master.getEncoding(); // always report from modified (right hand) side
|
||||
}
|
||||
|
||||
public setEncoding(encoding: string, mode: EncodingMode): void {
|
||||
[this.master, this.details].forEach(s => s.setEncoding(encoding, mode));
|
||||
}
|
||||
}
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
import { QueryEditorService } from 'sql/parts/query/services/queryEditorService';
|
||||
|
||||
function toEditorWithEncodingSupport(input: IEditorInput): IEncodingSupport {
|
||||
if (input instanceof SideBySideEditorInput) {
|
||||
input = input.master;
|
||||
}
|
||||
|
||||
// Untitled Editor
|
||||
if (input instanceof UntitledEditorInput) {
|
||||
return input;
|
||||
}
|
||||
|
||||
// Side by Side (diff) Editor
|
||||
if (input instanceof SideBySideEditorInput) {
|
||||
const masterEncodingSupport = toEditorWithEncodingSupport(input.master);
|
||||
const detailsEncodingSupport = toEditorWithEncodingSupport(input.details);
|
||||
|
||||
if (masterEncodingSupport && detailsEncodingSupport) {
|
||||
return new SideBySideEditorEncodingSupport(masterEncodingSupport, detailsEncodingSupport);
|
||||
}
|
||||
|
||||
return masterEncodingSupport;
|
||||
}
|
||||
|
||||
// File or Resource Editor
|
||||
let encodingSupport = input as IFileEditorInput;
|
||||
if (types.areFunctions(encodingSupport.setEncoding, encodingSupport.getEncoding)) {
|
||||
return encodingSupport;
|
||||
}
|
||||
|
||||
// Unsupported for any other editor
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -246,16 +269,16 @@ 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 {
|
||||
function setDisplay(el: HTMLElement, desiredValue: string): void {
|
||||
if (el.style.display !== desiredValue) {
|
||||
el.style.display = desiredValue;
|
||||
}
|
||||
}
|
||||
function show(el: HTMLElement): void {
|
||||
_setDisplay(el, '');
|
||||
setDisplay(el, '');
|
||||
}
|
||||
function hide(el: HTMLElement): void {
|
||||
_setDisplay(el, 'none');
|
||||
setDisplay(el, 'none');
|
||||
}
|
||||
|
||||
export class EditorStatus implements IStatusbarItem {
|
||||
@@ -274,7 +297,7 @@ export class EditorStatus implements IStatusbarItem {
|
||||
private activeEditorListeners: IDisposable[];
|
||||
private delayedRender: IDisposable;
|
||||
private toRender: StateChange;
|
||||
private lastScreenReaderExplanation: ScreenReaderDetectedExplanation;
|
||||
private screenReaderExplanation: ScreenReaderDetectedExplanation;
|
||||
|
||||
constructor(
|
||||
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
|
||||
@@ -289,7 +312,6 @@ export class EditorStatus implements IStatusbarItem {
|
||||
this.toDispose = [];
|
||||
this.activeEditorListeners = [];
|
||||
this.state = new State();
|
||||
this.lastScreenReaderExplanation = null;
|
||||
}
|
||||
|
||||
public render(container: HTMLElement): IDisposable {
|
||||
@@ -313,7 +335,7 @@ export class EditorStatus implements IStatusbarItem {
|
||||
hide(this.selectionElement);
|
||||
|
||||
this.indentationElement = append(this.element, $('a.editor-status-indentation'));
|
||||
this.indentationElement.title = nls.localize('indentation', "Indentation");
|
||||
this.indentationElement.title = nls.localize('selectIndentation', "Select Indentation");
|
||||
this.indentationElement.onclick = () => this.onIndentationClick();
|
||||
hide(this.indentationElement);
|
||||
|
||||
@@ -487,7 +509,18 @@ export class EditorStatus implements IStatusbarItem {
|
||||
}
|
||||
|
||||
private onScreenReaderModeClick(): void {
|
||||
this.lastScreenReaderExplanation = this.instantiationService.createInstance(ScreenReaderDetectedExplanation, this.screenRedearModeElement);
|
||||
const showExplanation = !this.screenReaderExplanation || !this.screenReaderExplanation.visible;
|
||||
|
||||
if (!this.screenReaderExplanation) {
|
||||
this.screenReaderExplanation = this.instantiationService.createInstance(ScreenReaderDetectedExplanation);
|
||||
this.toDispose.push(this.screenReaderExplanation);
|
||||
}
|
||||
|
||||
if (showExplanation) {
|
||||
this.screenReaderExplanation.show(this.screenRedearModeElement);
|
||||
} else {
|
||||
this.screenReaderExplanation.hide();
|
||||
}
|
||||
}
|
||||
|
||||
private onSelectionClick(): void {
|
||||
@@ -652,9 +685,8 @@ export class EditorStatus implements IStatusbarItem {
|
||||
screenReaderMode = (editorWidget.getConfiguration().accessibilitySupport === AccessibilitySupport.Enabled);
|
||||
}
|
||||
|
||||
if (screenReaderMode === false && this.lastScreenReaderExplanation) {
|
||||
this.lastScreenReaderExplanation.hide();
|
||||
this.lastScreenReaderExplanation = null;
|
||||
if (screenReaderMode === false && this.screenReaderExplanation && this.screenReaderExplanation.visible) {
|
||||
this.screenReaderExplanation.hide();
|
||||
}
|
||||
|
||||
this.updateState({ screenReaderMode: screenReaderMode });
|
||||
@@ -1229,113 +1261,148 @@ export class ChangeEncodingAction extends Action {
|
||||
}
|
||||
}
|
||||
|
||||
class ScreenReaderDetectedExplanation {
|
||||
|
||||
private _isDisposed: boolean;
|
||||
private _toDispose: IDisposable[];
|
||||
class ScreenReaderDetectedExplanation extends Themable {
|
||||
private container: HTMLElement;
|
||||
private hrElement: HTMLHRElement;
|
||||
private _visible: boolean;
|
||||
|
||||
constructor(
|
||||
anchorElement: HTMLElement,
|
||||
@IThemeService private readonly themeService: IThemeService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IContextViewService private readonly contextViewService: IContextViewService,
|
||||
@IWorkspaceConfigurationService private readonly configurationService: IWorkspaceConfigurationService,
|
||||
) {
|
||||
this._isDisposed = false;
|
||||
this._toDispose = [];
|
||||
super(themeService);
|
||||
}
|
||||
|
||||
public get visible(): boolean {
|
||||
return this._visible;
|
||||
}
|
||||
|
||||
protected updateStyles(): void {
|
||||
if (this.container) {
|
||||
const background = this.getColor(editorWidgetBackground);
|
||||
this.container.style.backgroundColor = background ? background.toString() : null;
|
||||
|
||||
const widgetShadowColor = this.getColor(widgetShadow);
|
||||
this.container.style.boxShadow = widgetShadowColor ? `0 0px 8px ${widgetShadowColor}` : null;
|
||||
|
||||
const contrastBorderColor = this.getColor(contrastBorder);
|
||||
this.container.style.border = contrastBorderColor ? `1px solid ${contrastBorderColor}` : null;
|
||||
|
||||
const foregroundColor = this.getColor(foreground);
|
||||
this.hrElement.style.backgroundColor = foregroundColor ? foregroundColor.toString() : null;
|
||||
}
|
||||
}
|
||||
|
||||
public show(anchorElement: HTMLElement): void {
|
||||
this._visible = true;
|
||||
|
||||
this.contextViewService.showContextView({
|
||||
getAnchor: () => anchorElement,
|
||||
getAnchor: () => {
|
||||
const res = getDomNodePagePosition(anchorElement);
|
||||
|
||||
return {
|
||||
x: res.left,
|
||||
y: res.top - 9, /* above the status bar */
|
||||
width: res.width,
|
||||
height: res.height
|
||||
} as IAnchor;
|
||||
},
|
||||
render: (container) => {
|
||||
return this.renderContents(container);
|
||||
},
|
||||
|
||||
onDOMEvent: (e, activeElement) => {
|
||||
},
|
||||
|
||||
onDOMEvent: (e, activeElement) => { },
|
||||
onHide: () => {
|
||||
this.dispose();
|
||||
this._visible = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this._isDisposed = true;
|
||||
this._toDispose = dispose(this._toDispose);
|
||||
}
|
||||
|
||||
public hide(): void {
|
||||
if (this._isDisposed) {
|
||||
return;
|
||||
}
|
||||
this.contextViewService.hideContextView();
|
||||
}
|
||||
|
||||
protected renderContents(container: HTMLElement): IDisposable {
|
||||
const domNode = $('div.screen-reader-detected-explanation', {
|
||||
protected renderContents(parent: HTMLElement): IDisposable {
|
||||
const toDispose: IDisposable[] = [];
|
||||
|
||||
this.container = $('div.screen-reader-detected-explanation', {
|
||||
'aria-hidden': 'true'
|
||||
});
|
||||
|
||||
const title = $('h2.title', {}, nls.localize('screenReaderDetectedExplanation.title', "Screen Reader Optimized"));
|
||||
domNode.appendChild(title);
|
||||
this.container.appendChild(title);
|
||||
|
||||
const closeBtn = $('div.cancel');
|
||||
this._toDispose.push(addDisposableListener(closeBtn, 'click', () => {
|
||||
toDispose.push(addDisposableListener(closeBtn, 'click', () => {
|
||||
this.contextViewService.hideContextView();
|
||||
}));
|
||||
domNode.appendChild(closeBtn);
|
||||
toDispose.push(addDisposableListener(closeBtn, 'mouseover', () => {
|
||||
const theme = this.themeService.getTheme();
|
||||
let darkenFactor: number;
|
||||
switch (theme.type) {
|
||||
case 'light':
|
||||
darkenFactor = 0.1;
|
||||
break;
|
||||
case 'dark':
|
||||
darkenFactor = 0.2;
|
||||
break;
|
||||
}
|
||||
|
||||
if (darkenFactor) {
|
||||
closeBtn.style.backgroundColor = this.getColor(editorWidgetBackground, (color, theme) => darken(color, darkenFactor)(theme));
|
||||
}
|
||||
}));
|
||||
toDispose.push(addDisposableListener(closeBtn, 'mouseout', () => {
|
||||
closeBtn.style.backgroundColor = null;
|
||||
}));
|
||||
this.container.appendChild(closeBtn);
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
const question = $('p.question', {}, nls.localize('screenReaderDetectedExplanation.question', "Are you using a screen reader to operate SQL Operations Studio?"));
|
||||
domNode.appendChild(question);
|
||||
this.container.appendChild(question);
|
||||
|
||||
const buttonContainer = $('div.buttons');
|
||||
domNode.appendChild(buttonContainer);
|
||||
this.container.appendChild(buttonContainer);
|
||||
|
||||
const yesBtn = new Button(buttonContainer);
|
||||
yesBtn.label = nls.localize('screenReaderDetectedExplanation.answerYes', "Yes");
|
||||
this._toDispose.push(attachButtonStyler(yesBtn, this.themeService));
|
||||
this._toDispose.push(yesBtn.onDidClick(e => {
|
||||
toDispose.push(attachButtonStyler(yesBtn, this.themeService));
|
||||
toDispose.push(yesBtn.onDidClick(e => {
|
||||
this.configurationService.updateValue('editor.accessibilitySupport', 'on', ConfigurationTarget.USER);
|
||||
this.contextViewService.hideContextView();
|
||||
}));
|
||||
|
||||
const noBtn = new Button(buttonContainer);
|
||||
noBtn.label = nls.localize('screenReaderDetectedExplanation.answerNo', "No");
|
||||
this._toDispose.push(attachButtonStyler(noBtn, this.themeService));
|
||||
this._toDispose.push(noBtn.onDidClick(e => {
|
||||
toDispose.push(attachButtonStyler(noBtn, this.themeService));
|
||||
toDispose.push(noBtn.onDidClick(e => {
|
||||
this.configurationService.updateValue('editor.accessibilitySupport', 'off', ConfigurationTarget.USER);
|
||||
this.contextViewService.hideContextView();
|
||||
}));
|
||||
|
||||
const clear = $('div');
|
||||
clear.style.clear = 'both';
|
||||
domNode.appendChild(clear);
|
||||
this.container.appendChild(clear);
|
||||
|
||||
const br = $('br');
|
||||
domNode.appendChild(br);
|
||||
this.container.appendChild(br);
|
||||
|
||||
const hr = $('hr');
|
||||
domNode.appendChild(hr);
|
||||
this.hrElement = $('hr');
|
||||
this.container.appendChild(this.hrElement);
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
const explanation1 = $('p.body1', {}, nls.localize('screenReaderDetectedExplanation.body1', "SQL Operations Studio is now optimized for usage with a screen reader."));
|
||||
domNode.appendChild(explanation1);
|
||||
this.container.appendChild(explanation1);
|
||||
|
||||
const explanation2 = $('p.body2', {}, nls.localize('screenReaderDetectedExplanation.body2', "Some editor features will have different behaviour: e.g. word wrapping, folding, etc."));
|
||||
domNode.appendChild(explanation2);
|
||||
this.container.appendChild(explanation2);
|
||||
|
||||
container.appendChild(domNode);
|
||||
parent.appendChild(this.container);
|
||||
|
||||
this._toDispose.push(attachStylerCallback(this.themeService, { widgetShadow, editorWidgetBackground }, colors => {
|
||||
domNode.style.backgroundColor = colors.editorWidgetBackground;
|
||||
if (colors.widgetShadow) {
|
||||
domNode.style.boxShadow = `0 5px 8px ${colors.widgetShadow}`;
|
||||
}
|
||||
}));
|
||||
this.updateStyles();
|
||||
|
||||
return {
|
||||
dispose: () => { this.dispose(); }
|
||||
dispose: () => dispose(toDispose)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.monaco-workbench .quick-open-widget .quick-open-tree .quick-open-entry.editor-preview {
|
||||
.monaco-workbench .monaco-quick-open-widget .quick-open-tree .quick-open-entry.editor-preview {
|
||||
font-style: italic;
|
||||
}
|
||||
@@ -22,7 +22,6 @@
|
||||
cursor: default !important;
|
||||
}
|
||||
|
||||
|
||||
.monaco-shell .screen-reader-detected-explanation {
|
||||
width: 420px;
|
||||
top: 30px;
|
||||
@@ -53,8 +52,9 @@
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.monaco-shell .screen-reader-detected-explanation p.question {
|
||||
font-size: 1.4em;
|
||||
.monaco-shell .screen-reader-detected-explanation hr {
|
||||
border: 0;
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
.monaco-shell .screen-reader-detected-explanation .buttons {
|
||||
@@ -72,21 +72,8 @@
|
||||
.monaco-shell.vs .screen-reader-detected-explanation .cancel {
|
||||
background: url('close-big.svg') center center no-repeat;
|
||||
}
|
||||
.monaco-shell.vs .screen-reader-detected-explanation .cancel:hover {
|
||||
background-color: #eaeaea;
|
||||
}
|
||||
|
||||
.monaco-shell.vs-dark .screen-reader-detected-explanation .cancel,
|
||||
.monaco-shell.hc-black .screen-reader-detected-explanation .cancel {
|
||||
background: url('close-big-dark.svg') center center no-repeat;
|
||||
}
|
||||
.monaco-shell.vs-dark .screen-reader-detected-explanation .cancel:hover {
|
||||
background-color: rgba(30,30,30,0.8);
|
||||
}
|
||||
|
||||
.monaco-shell.hc-black .screen-reader-detected-explanation .cancel {
|
||||
opacity: 0.6;
|
||||
}
|
||||
.monaco-shell.hc-black .screen-reader-detected-explanation .cancel:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@@ -54,8 +54,9 @@
|
||||
cursor: zoom-out;
|
||||
}
|
||||
|
||||
.monaco-resource-viewer .open-external,
|
||||
.monaco-resource-viewer .open-external:hover {
|
||||
.monaco-resource-viewer .embedded-link,
|
||||
.monaco-resource-viewer .embedded-link:hover {
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
@@ -62,15 +62,24 @@
|
||||
max-width: fit-content;
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.sizing-shrink.close-button-left::after,
|
||||
.monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.sizing-shrink.close-button-off::after {
|
||||
content: "";
|
||||
display: flex;
|
||||
flex: 0;
|
||||
width: 5px; /* Reserve space to hide tab fade when close button is left or off (fixes https://github.com/Microsoft/vscode/issues/45728) */
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.sizing-shrink.close-button-left {
|
||||
min-width: 80px; /* make more room for close button when it shows to the left */
|
||||
padding-right: 5px; /* we need less room when sizing is shrink */
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.dragged {
|
||||
will-change: transform; /* forces tab to be drawn on a separate layer (fixes https://github.com/Microsoft/vscode/issues/18733) */
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.dragged-over * {
|
||||
.monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.dragged-over div {
|
||||
pointer-events: none; /* prevents cursor flickering (fixes https://github.com/Microsoft/vscode/issues/38753) */
|
||||
}
|
||||
|
||||
@@ -190,6 +199,10 @@
|
||||
padding-right: 10px; /* give a little bit more room if close button is off */
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.sizing-shrink.close-button-off {
|
||||
padding-right: 5px; /* we need less room when sizing is shrink */
|
||||
}
|
||||
|
||||
.monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.close-button-off.dirty {
|
||||
background-repeat: no-repeat;
|
||||
background-position-y: center;
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
'use strict';
|
||||
|
||||
import 'vs/css!./media/notabstitle';
|
||||
import errors = require('vs/base/common/errors');
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import { toResource } from 'vs/workbench/common/editor';
|
||||
import DOM = require('vs/base/browser/dom');
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { TitleControl } from 'vs/workbench/browser/parts/editor/titleControl';
|
||||
import { ResourceLabel } from 'vs/workbench/browser/labels';
|
||||
import { Verbosity } from 'vs/platform/editor/common/editor';
|
||||
@@ -81,14 +81,14 @@ export class NoTabsTitleControl extends TitleControl {
|
||||
|
||||
// Close editor on middle mouse click
|
||||
if (e instanceof MouseEvent && e.button === 1 /* Middle Button */) {
|
||||
this.closeEditorAction.run({ groupId: group.id, editorIndex: group.indexOf(group.activeEditor) }).done(null, errors.onUnexpectedError);
|
||||
this.closeOneEditorAction.run({ groupId: group.id, editorIndex: group.indexOf(group.activeEditor) }).done(null, errors.onUnexpectedError);
|
||||
}
|
||||
|
||||
// Focus editor group unless:
|
||||
// - click on toolbar: should trigger actions within
|
||||
// - mouse click: do not focus group if there are more than one as it otherwise makes group DND funky
|
||||
// - touch: always focus
|
||||
else if ((this.stacks.groups.length === 1 || !(e instanceof MouseEvent)) && !DOM.isAncestor(((e as GestureEvent).initialTarget || e.target || e.srcElement) as HTMLElement, this.editorActionsToolbar.getContainer().getHTMLElement())) {
|
||||
else if ((this.stacks.groups.length === 1 || !(e instanceof MouseEvent)) && !DOM.isAncestor(((e as GestureEvent).initialTarget || e.target || e.srcElement) as HTMLElement, this.editorActionsToolbar.getContainer())) {
|
||||
this.editorGroupService.focusGroup(group);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IRange } from 'vs/editor/common/core/range';
|
||||
import { CursorChangeReason, ICursorPositionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
|
||||
@@ -25,10 +25,10 @@ export class RangeHighlightDecorations implements IDisposable {
|
||||
private editor: ICodeEditor = null;
|
||||
private editorDisposables: IDisposable[] = [];
|
||||
|
||||
private _onHighlightRemoved: Emitter<void> = new Emitter<void>();
|
||||
private readonly _onHighlightRemoved: Emitter<void> = new Emitter<void>();
|
||||
public readonly onHighlghtRemoved: Event<void> = this._onHighlightRemoved.event;
|
||||
|
||||
constructor( @IWorkbenchEditorService private editorService: IWorkbenchEditorService) {
|
||||
constructor(@IWorkbenchEditorService private editorService: IWorkbenchEditorService) {
|
||||
}
|
||||
|
||||
public removeHighlightRange() {
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
'use strict';
|
||||
|
||||
import 'vs/css!./media/resourceviewer';
|
||||
import nls = require('vs/nls');
|
||||
import mimes = require('vs/base/common/mime');
|
||||
import * as nls from 'vs/nls';
|
||||
import * as mimes from 'vs/base/common/mime';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import paths = require('vs/base/common/paths');
|
||||
import { Builder, $, Dimension } from 'vs/base/browser/builder';
|
||||
import DOM = require('vs/base/browser/dom');
|
||||
import * as paths from 'vs/base/common/paths';
|
||||
import { Builder, $ } from 'vs/base/browser/builder';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
|
||||
import { LRUCache } from 'vs/base/common/map';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
@@ -19,7 +19,6 @@ import { clamp } from 'vs/base/common/numbers';
|
||||
import { Themable } from 'vs/workbench/common/theme';
|
||||
import { IStatusbarItem, StatusbarItemDescriptor, IStatusbarRegistry, Extensions, StatusbarAlignment } from 'vs/workbench/browser/parts/statusbar/statusbar';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { } from 'vs/platform/workspace/common/workspace';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
@@ -119,7 +118,7 @@ class BinarySize {
|
||||
}
|
||||
|
||||
export interface ResourceViewerContext {
|
||||
layout(dimension: Dimension): void;
|
||||
layout(dimension: DOM.Dimension): void;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,26 +126,42 @@ export interface ResourceViewerContext {
|
||||
* progress of the binary resource.
|
||||
*/
|
||||
export class ResourceViewer {
|
||||
|
||||
private static readonly MAX_OPEN_INTERNAL_SIZE = BinarySize.MB * 200; // max size until we offer an action to open internally
|
||||
|
||||
public static show(
|
||||
descriptor: IResourceDescriptor,
|
||||
container: Builder,
|
||||
container: HTMLElement,
|
||||
scrollbar: DomScrollableElement,
|
||||
openExternal: (uri: URI) => void,
|
||||
openInternalClb: (uri: URI) => void,
|
||||
openExternalClb: (uri: URI) => void,
|
||||
metadataClb: (meta: string) => void
|
||||
): ResourceViewerContext {
|
||||
): ResourceViewerContext | null {
|
||||
|
||||
// Ensure CSS class
|
||||
$(container).setClass('monaco-resource-viewer');
|
||||
|
||||
// Images
|
||||
if (ResourceViewer.isImageResource(descriptor)) {
|
||||
return ImageView.create(container, descriptor, scrollbar, openExternal, metadataClb);
|
||||
return ImageView.create(container, descriptor, scrollbar, openExternalClb, metadataClb);
|
||||
}
|
||||
|
||||
// Large Files
|
||||
if (descriptor.size > ResourceViewer.MAX_OPEN_INTERNAL_SIZE) {
|
||||
FileTooLargeFileView.create(container, descriptor, scrollbar, metadataClb);
|
||||
}
|
||||
|
||||
// Seemingly Binary Files
|
||||
else {
|
||||
FileSeemsBinaryFileView.create(container, descriptor, scrollbar, openInternalClb, metadataClb);
|
||||
}
|
||||
|
||||
GenericBinaryFileView.create(container, metadataClb, descriptor, scrollbar);
|
||||
return null;
|
||||
}
|
||||
|
||||
private static isImageResource(descriptor: IResourceDescriptor) {
|
||||
const mime = ResourceViewer.getMime(descriptor);
|
||||
|
||||
return mime.indexOf('image/') >= 0;
|
||||
}
|
||||
|
||||
@@ -158,6 +173,7 @@ export class ResourceViewer {
|
||||
mime = mapExtToMediaMimes[ext.toLowerCase()];
|
||||
}
|
||||
}
|
||||
|
||||
return mime || mimes.MIME_BINARY;
|
||||
}
|
||||
}
|
||||
@@ -167,17 +183,18 @@ class ImageView {
|
||||
private static readonly BASE64_MARKER = 'base64,';
|
||||
|
||||
public static create(
|
||||
container: Builder,
|
||||
container: HTMLElement,
|
||||
descriptor: IResourceDescriptor,
|
||||
scrollbar: DomScrollableElement,
|
||||
openExternal: (uri: URI) => void,
|
||||
openExternalClb: (uri: URI) => void,
|
||||
metadataClb: (meta: string) => void
|
||||
): ResourceViewerContext | null {
|
||||
if (ImageView.shouldShowImageInline(descriptor)) {
|
||||
return InlineImageView.create(container, descriptor, scrollbar, metadataClb);
|
||||
}
|
||||
|
||||
LargeImageView.create(container, descriptor, openExternal);
|
||||
LargeImageView.create(container, descriptor, openExternalClb);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -203,43 +220,81 @@ class ImageView {
|
||||
|
||||
class LargeImageView {
|
||||
public static create(
|
||||
container: Builder,
|
||||
container: HTMLElement,
|
||||
descriptor: IResourceDescriptor,
|
||||
openExternal: (uri: URI) => void
|
||||
openExternalClb: (uri: URI) => void
|
||||
) {
|
||||
const size = BinarySize.formatSize(descriptor.size);
|
||||
|
||||
const imageContainer = $(container)
|
||||
.empty()
|
||||
.p({
|
||||
text: nls.localize('largeImageError', "The file size of the image is too large (>1MB) to display in the editor. ")
|
||||
text: nls.localize('largeImageError', "The image is not displayed in the editor because it is too large ({0}).", size)
|
||||
});
|
||||
|
||||
if (descriptor.resource.scheme !== Schemas.data) {
|
||||
imageContainer.append($('a', {
|
||||
role: 'button',
|
||||
class: 'open-external',
|
||||
class: 'embedded-link',
|
||||
text: nls.localize('resourceOpenExternalButton', "Open image using external program?")
|
||||
}).on(DOM.EventType.CLICK, (e) => {
|
||||
openExternal(descriptor.resource);
|
||||
openExternalClb(descriptor.resource);
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class GenericBinaryFileView {
|
||||
class FileTooLargeFileView {
|
||||
public static create(
|
||||
container: Builder,
|
||||
metadataClb: (meta: string) => void,
|
||||
container: HTMLElement,
|
||||
descriptor: IResourceDescriptor,
|
||||
scrollbar: DomScrollableElement
|
||||
scrollbar: DomScrollableElement,
|
||||
metadataClb: (meta: string) => void
|
||||
) {
|
||||
const size = BinarySize.formatSize(descriptor.size);
|
||||
|
||||
$(container)
|
||||
.empty()
|
||||
.span({
|
||||
text: nls.localize('nativeBinaryError', "The file will not be displayed in the editor because it is either binary, very large or uses an unsupported text encoding.")
|
||||
text: nls.localize('nativeFileTooLargeError', "The file is not displayed in the editor because it is too large ({0}).", size)
|
||||
});
|
||||
|
||||
if (metadataClb) {
|
||||
metadataClb(size);
|
||||
}
|
||||
|
||||
scrollbar.scanDomNode();
|
||||
}
|
||||
}
|
||||
|
||||
class FileSeemsBinaryFileView {
|
||||
public static create(
|
||||
container: HTMLElement,
|
||||
descriptor: IResourceDescriptor,
|
||||
scrollbar: DomScrollableElement,
|
||||
openInternalClb: (uri: URI) => void,
|
||||
metadataClb: (meta: string) => void
|
||||
) {
|
||||
const binaryContainer = $(container)
|
||||
.empty()
|
||||
.p({
|
||||
text: nls.localize('nativeBinaryError', "The file is not displayed in the editor because it is either binary or uses an unsupported text encoding.")
|
||||
});
|
||||
|
||||
if (descriptor.resource.scheme !== Schemas.data) {
|
||||
binaryContainer.append($('a', {
|
||||
role: 'button',
|
||||
class: 'embedded-link',
|
||||
text: nls.localize('openAsText', "Do you want to open it anyway?")
|
||||
}).on(DOM.EventType.CLICK, (e) => {
|
||||
openInternalClb(descriptor.resource);
|
||||
}));
|
||||
}
|
||||
|
||||
if (metadataClb) {
|
||||
metadataClb(BinarySize.formatSize(descriptor.size));
|
||||
}
|
||||
|
||||
scrollbar.scanDomNode();
|
||||
}
|
||||
}
|
||||
@@ -266,7 +321,7 @@ class ZoomStatusbarItem extends Themable implements IStatusbarItem {
|
||||
|
||||
private onEditorsChanged(): void {
|
||||
this.hide();
|
||||
this.onSelectScale = undefined;
|
||||
this.onSelectScale = void 0;
|
||||
}
|
||||
|
||||
public show(scale: Scale, onSelectScale: (scale: number) => void) {
|
||||
@@ -295,6 +350,7 @@ class ZoomStatusbarItem extends Themable implements IStatusbarItem {
|
||||
.getHTMLElement();
|
||||
this.statusBarItem.style.display = 'none';
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -306,10 +362,11 @@ class ZoomStatusbarItem extends Themable implements IStatusbarItem {
|
||||
private get zoomActions(): Action[] {
|
||||
const scales: Scale[] = [10, 5, 2, 1, 0.5, 0.2, 'fit'];
|
||||
return scales.map(scale =>
|
||||
new Action('zoom.' + scale, ZoomStatusbarItem.zoomLabel(scale), undefined, undefined, () => {
|
||||
new Action(`zoom.${scale}`, ZoomStatusbarItem.zoomLabel(scale), void 0, void 0, () => {
|
||||
if (this.onSelectScale) {
|
||||
this.onSelectScale(scale);
|
||||
}
|
||||
|
||||
return null;
|
||||
}));
|
||||
}
|
||||
@@ -376,13 +433,13 @@ class InlineImageView {
|
||||
private static readonly imageStateCache = new LRUCache<string, ImageState>(100);
|
||||
|
||||
public static create(
|
||||
container: Builder,
|
||||
container: HTMLElement,
|
||||
descriptor: IResourceDescriptor,
|
||||
scrollbar: DomScrollableElement,
|
||||
metadataClb: (meta: string) => void
|
||||
) {
|
||||
const context = {
|
||||
layout(dimension: Dimension) { }
|
||||
layout(dimension: DOM.Dimension) { }
|
||||
};
|
||||
|
||||
const cacheKey = descriptor.resource.toString();
|
||||
@@ -585,6 +642,4 @@ class InlineImageView {
|
||||
|
||||
return cached.src;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -5,14 +5,11 @@
|
||||
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { Dimension, Builder } from 'vs/base/browser/builder';
|
||||
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { EditorInput, EditorOptions, SideBySideEditorInput } from 'vs/workbench/common/editor';
|
||||
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
|
||||
import { IEditorControl, Position, IEditor } from 'vs/platform/editor/common/editor';
|
||||
import { VSash } from 'vs/base/browser/ui/sash/sash';
|
||||
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
@@ -23,7 +20,7 @@ export class SideBySideEditor extends BaseEditor {
|
||||
|
||||
public static readonly ID: string = 'workbench.editor.sidebysideEditor';
|
||||
|
||||
private dimension: Dimension;
|
||||
private dimension: DOM.Dimension;
|
||||
|
||||
protected masterEditor: BaseEditor;
|
||||
private masterEditorContainer: HTMLElement;
|
||||
@@ -41,10 +38,9 @@ export class SideBySideEditor extends BaseEditor {
|
||||
super(SideBySideEditor.ID, telemetryService, themeService);
|
||||
}
|
||||
|
||||
protected createEditor(parent: Builder): void {
|
||||
const parentElement = parent.getHTMLElement();
|
||||
DOM.addClass(parentElement, 'side-by-side-editor');
|
||||
this.createSash(parentElement);
|
||||
protected createEditor(parent: HTMLElement): void {
|
||||
DOM.addClass(parent, 'side-by-side-editor');
|
||||
this.createSash(parent);
|
||||
}
|
||||
|
||||
public setInput(newInput: SideBySideEditorInput, options?: EditorOptions): TPromise<void> {
|
||||
@@ -90,7 +86,7 @@ export class SideBySideEditor extends BaseEditor {
|
||||
}
|
||||
}
|
||||
|
||||
public layout(dimension: Dimension): void {
|
||||
public layout(dimension: DOM.Dimension): void {
|
||||
this.dimension = dimension;
|
||||
this.sash.setDimenesion(this.dimension);
|
||||
}
|
||||
@@ -110,6 +106,10 @@ export class SideBySideEditor extends BaseEditor {
|
||||
return this.detailsEditor;
|
||||
}
|
||||
|
||||
public supportsCenteredLayout(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
private updateInput(oldInput: SideBySideEditorInput, newInput: SideBySideEditorInput, options?: EditorOptions): void {
|
||||
if (!newInput.matches(oldInput)) {
|
||||
if (oldInput) {
|
||||
@@ -137,7 +137,7 @@ export class SideBySideEditor extends BaseEditor {
|
||||
const descriptor = Registry.as<IEditorRegistry>(EditorExtensions.Editors).getEditor(editorInput);
|
||||
|
||||
const editor = descriptor.instantiate(this.instantiationService);
|
||||
editor.create(new Builder(container));
|
||||
editor.create(container);
|
||||
editor.setVisible(this.isVisible(), this.position);
|
||||
|
||||
return editor;
|
||||
@@ -151,7 +151,7 @@ export class SideBySideEditor extends BaseEditor {
|
||||
}
|
||||
|
||||
private createEditorContainers(): void {
|
||||
const parentElement = this.getContainer().getHTMLElement();
|
||||
const parentElement = this.getContainer();
|
||||
this.detailsEditorContainer = DOM.append(parentElement, DOM.$('.details-editor-container'));
|
||||
this.detailsEditorContainer.style.position = 'absolute';
|
||||
this.masterEditorContainer = DOM.append(parentElement, DOM.$('.master-editor-container'));
|
||||
@@ -188,12 +188,12 @@ export class SideBySideEditor extends BaseEditor {
|
||||
this.masterEditorContainer.style.height = `${this.dimension.height}px`;
|
||||
this.masterEditorContainer.style.left = `${splitPoint}px`;
|
||||
|
||||
this.detailsEditor.layout(new Dimension(detailsEditorWidth, this.dimension.height));
|
||||
this.masterEditor.layout(new Dimension(masterEditorWidth, this.dimension.height));
|
||||
this.detailsEditor.layout(new DOM.Dimension(detailsEditorWidth, this.dimension.height));
|
||||
this.masterEditor.layout(new DOM.Dimension(masterEditorWidth, this.dimension.height));
|
||||
}
|
||||
|
||||
private disposeEditors(): void {
|
||||
const parentContainer = this.getContainer().getHTMLElement();
|
||||
const parentContainer = this.getContainer();
|
||||
if (this.detailsEditor) {
|
||||
this.detailsEditor.dispose();
|
||||
this.detailsEditor = null;
|
||||
@@ -216,4 +216,4 @@ export class SideBySideEditor extends BaseEditor {
|
||||
this.disposeEditors();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
'use strict';
|
||||
|
||||
import 'vs/css!./media/tabstitle';
|
||||
import nls = require('vs/nls');
|
||||
import * as nls from 'vs/nls';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import errors = require('vs/base/common/errors');
|
||||
import DOM = require('vs/base/browser/dom');
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { isMacintosh } from 'vs/base/common/platform';
|
||||
import { shorten } from 'vs/base/common/labels';
|
||||
import { ActionRunner, IAction } from 'vs/base/common/actions';
|
||||
@@ -38,8 +38,6 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle
|
||||
import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
|
||||
import { TAB_INACTIVE_BACKGROUND, TAB_ACTIVE_BACKGROUND, TAB_ACTIVE_FOREGROUND, TAB_INACTIVE_FOREGROUND, TAB_BORDER, EDITOR_DRAG_AND_DROP_BACKGROUND, TAB_UNFOCUSED_ACTIVE_FOREGROUND, TAB_UNFOCUSED_INACTIVE_FOREGROUND, TAB_UNFOCUSED_ACTIVE_BORDER, TAB_ACTIVE_BORDER, TAB_HOVER_BACKGROUND, TAB_HOVER_BORDER, TAB_UNFOCUSED_HOVER_BACKGROUND, TAB_UNFOCUSED_HOVER_BORDER, EDITOR_GROUP_HEADER_TABS_BACKGROUND, EDITOR_GROUP_BACKGROUND, WORKBENCH_BACKGROUND } from 'vs/workbench/common/theme';
|
||||
import { activeContrastBorder, contrastBorder, editorBackground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { Dimension } from 'vs/base/browser/builder';
|
||||
import { scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
|
||||
import { ResourcesDropHandler, fillResourceDataTransfers, LocalSelectionTransfer, DraggedEditorIdentifier } from 'vs/workbench/browser/dnd';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
@@ -72,7 +70,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
private scrollbar: ScrollableElement;
|
||||
private tabDisposeables: IDisposable[];
|
||||
private blockRevealActiveTab: boolean;
|
||||
private dimension: Dimension;
|
||||
private dimension: DOM.Dimension;
|
||||
private layoutScheduled: IDisposable;
|
||||
private transfer = LocalSelectionTransfer.getInstance<DraggedEditorIdentifier>();
|
||||
|
||||
@@ -576,7 +574,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
this.tabDisposeables.push(actionRunner);
|
||||
|
||||
const bar = new ActionBar(tabCloseContainer, { ariaLabel: nls.localize('araLabelTabActions', "Tab actions"), actionRunner });
|
||||
bar.push(this.closeEditorAction, { icon: true, label: false, keybinding: this.getKeybindingLabel(this.closeEditorAction) });
|
||||
bar.push(this.closeOneEditorAction, { icon: true, label: false, keybinding: this.getKeybindingLabel(this.closeOneEditorAction) });
|
||||
|
||||
// Eventing
|
||||
const disposable = this.hookTabListeners(tabContainer, index);
|
||||
@@ -586,7 +584,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
return tabContainer;
|
||||
}
|
||||
|
||||
public layout(dimension: Dimension): void {
|
||||
public layout(dimension: DOM.Dimension): void {
|
||||
if (!this.activeTab || !dimension) {
|
||||
return;
|
||||
}
|
||||
@@ -597,14 +595,14 @@ export class TabsTitleControl extends TitleControl {
|
||||
// that can result in the browser doing a full page layout to validate them. To buffer
|
||||
// this a little bit we try at least to schedule this work on the next animation frame.
|
||||
if (!this.layoutScheduled) {
|
||||
this.layoutScheduled = scheduleAtNextAnimationFrame(() => {
|
||||
this.layoutScheduled = DOM.scheduleAtNextAnimationFrame(() => {
|
||||
this.doLayout(this.dimension);
|
||||
this.layoutScheduled = void 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private doLayout(dimension: Dimension): void {
|
||||
private doLayout(dimension: DOM.Dimension): void {
|
||||
const visibleContainerWidth = this.tabsContainer.offsetWidth;
|
||||
const totalContainerWidth = this.tabsContainer.scrollWidth;
|
||||
|
||||
@@ -695,7 +693,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
tab.blur();
|
||||
|
||||
if (e.button === 1 /* Middle Button*/ && !this.isTabActionBar((e.target || e.srcElement) as HTMLElement)) {
|
||||
this.closeEditorAction.run({ groupId: this.context.id, editorIndex: index }).done(null, errors.onUnexpectedError);
|
||||
this.closeOneEditorAction.run({ groupId: this.context.id, editorIndex: index }).done(null, errors.onUnexpectedError);
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -789,7 +787,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
|
||||
// Fixes https://github.com/Microsoft/vscode/issues/18733
|
||||
DOM.addClass(tab, 'dragged');
|
||||
scheduleAtNextAnimationFrame(() => DOM.removeClass(tab, 'dragged'));
|
||||
DOM.scheduleAtNextAnimationFrame(() => DOM.removeClass(tab, 'dragged'));
|
||||
}));
|
||||
|
||||
// We need to keep track of DRAG_ENTER and DRAG_LEAVE events because a tab is not just a div without children,
|
||||
@@ -977,7 +975,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
if (tabHoverBackground) {
|
||||
collector.addRule(`
|
||||
.monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title.active .tabs-container > .tab:hover {
|
||||
background: ${tabHoverBackground} !important;
|
||||
background-color: ${tabHoverBackground} !important;
|
||||
}
|
||||
`);
|
||||
}
|
||||
@@ -986,7 +984,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
if (tabUnfocusedHoverBackground) {
|
||||
collector.addRule(`
|
||||
.monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title.inactive .tabs-container > .tab:hover {
|
||||
background: ${tabUnfocusedHoverBackground} !important;
|
||||
background-color: ${tabUnfocusedHoverBackground} !important;
|
||||
}
|
||||
`);
|
||||
}
|
||||
|
||||
@@ -7,12 +7,11 @@
|
||||
|
||||
import 'vs/css!./media/textdiffeditor';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import nls = require('vs/nls');
|
||||
import objects = require('vs/base/common/objects');
|
||||
import { Builder } from 'vs/base/browser/builder';
|
||||
import * as nls from 'vs/nls';
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
import { Action, IAction } from 'vs/base/common/actions';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import types = require('vs/base/common/types');
|
||||
import * as types from 'vs/base/common/types';
|
||||
import { IDiffEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { IDiffEditorOptions, IEditorOptions } from 'vs/editor/common/config/editorOptions';
|
||||
import { BaseTextEditor, IEditorConfiguration } from 'vs/workbench/browser/parts/editor/textEditor';
|
||||
@@ -32,10 +31,13 @@ import { IWorkbenchEditorService, DelegatingWorkbenchEditorService } from 'vs/wo
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService';
|
||||
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { ScrollType } from 'vs/editor/common/editorCommon';
|
||||
import { ScrollType, IDiffEditorViewState, IDiffEditorModel } from 'vs/editor/common/editorCommon';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { getCodeOrDiffEditor } from 'vs/editor/browser/services/codeEditorService';
|
||||
import { once } from 'vs/base/common/event';
|
||||
|
||||
/**
|
||||
* The text editor that leverages the diff text editor for the editing experience.
|
||||
@@ -45,10 +47,10 @@ export class TextDiffEditor extends BaseTextEditor {
|
||||
public static readonly ID = TEXT_DIFF_EDITOR_ID;
|
||||
|
||||
private diffNavigator: DiffNavigator;
|
||||
private diffNavigatorDisposables: IDisposable[];
|
||||
private nextDiffAction: NavigateAction;
|
||||
private previousDiffAction: NavigateAction;
|
||||
private toggleIgnoreTrimWhitespaceAction: ToggleIgnoreTrimWhitespaceAction;
|
||||
private _configurationListener: IDisposable;
|
||||
|
||||
constructor(
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@@ -63,11 +65,12 @@ export class TextDiffEditor extends BaseTextEditor {
|
||||
) {
|
||||
super(TextDiffEditor.ID, telemetryService, instantiationService, storageService, configurationService, themeService, textFileService, editorGroupService);
|
||||
|
||||
this._configurationListener = this._actualConfigurationService.onDidChangeConfiguration((e) => {
|
||||
this.diffNavigatorDisposables = [];
|
||||
this.toUnbind.push(this._actualConfigurationService.onDidChangeConfiguration((e) => {
|
||||
if (e.affectsConfiguration('diffEditor.ignoreTrimWhitespace')) {
|
||||
this.updateIgnoreTrimWhitespaceAction();
|
||||
}
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
public getTitle(): string {
|
||||
@@ -78,7 +81,7 @@ export class TextDiffEditor extends BaseTextEditor {
|
||||
return nls.localize('textDiffEditor', "Text Diff Editor");
|
||||
}
|
||||
|
||||
public createEditorControl(parent: Builder, configuration: IEditorOptions): IDiffEditor {
|
||||
public createEditorControl(parent: HTMLElement, configuration: IEditorOptions): IDiffEditor {
|
||||
|
||||
// Actions
|
||||
this.nextDiffAction = new NavigateAction(this, true);
|
||||
@@ -118,7 +121,7 @@ export class TextDiffEditor extends BaseTextEditor {
|
||||
// Create a special child of instantiator that will delegate all calls to openEditor() to the same diff editor if the input matches with the modified one
|
||||
const diffEditorInstantiator = this.instantiationService.createChild(new ServiceCollection([IWorkbenchEditorService, delegatingEditorService]));
|
||||
|
||||
return diffEditorInstantiator.createInstance(DiffEditorWidget, parent.getHTMLElement(), configuration);
|
||||
return diffEditorInstantiator.createInstance(DiffEditorWidget, parent, configuration);
|
||||
}
|
||||
|
||||
public setInput(input: EditorInput, options?: EditorOptions): TPromise<void> {
|
||||
@@ -137,9 +140,10 @@ export class TextDiffEditor extends BaseTextEditor {
|
||||
}
|
||||
|
||||
// Dispose previous diff navigator
|
||||
if (this.diffNavigator) {
|
||||
this.diffNavigator.dispose();
|
||||
}
|
||||
this.diffNavigatorDisposables = dispose(this.diffNavigatorDisposables);
|
||||
|
||||
// Remember view settings if input changes
|
||||
this.saveTextDiffEditorViewState(this.input);
|
||||
|
||||
// Set input and resolve
|
||||
return super.setInput(input, options).then(() => {
|
||||
@@ -155,27 +159,32 @@ export class TextDiffEditor extends BaseTextEditor {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Editor
|
||||
// Set Editor Model
|
||||
const diffEditor = <IDiffEditor>this.getControl();
|
||||
diffEditor.setModel((<TextDiffEditorModel>resolvedModel).textDiffEditorModel);
|
||||
|
||||
// Handle TextOptions
|
||||
let alwaysRevealFirst = true;
|
||||
// Apply Options from TextOptions
|
||||
let optionsGotApplied = false;
|
||||
if (options && types.isFunction((<TextEditorOptions>options).apply)) {
|
||||
const hadOptions = (<TextEditorOptions>options).apply(<IDiffEditor>diffEditor, ScrollType.Immediate);
|
||||
if (hadOptions) {
|
||||
alwaysRevealFirst = false; // Do not reveal if we are instructed to open specific line/col
|
||||
}
|
||||
optionsGotApplied = (<TextEditorOptions>options).apply(<IDiffEditor>diffEditor, ScrollType.Immediate);
|
||||
}
|
||||
|
||||
// Otherwise restore View State
|
||||
let hasPreviousViewState = false;
|
||||
if (!optionsGotApplied) {
|
||||
hasPreviousViewState = this.restoreTextDiffEditorViewState(input);
|
||||
}
|
||||
|
||||
// Listen on diff updated changes to reveal the first change
|
||||
this.diffNavigator = new DiffNavigator(diffEditor, {
|
||||
alwaysRevealFirst
|
||||
alwaysRevealFirst: !optionsGotApplied && !hasPreviousViewState // only reveal first change if we had no options or viewstate
|
||||
});
|
||||
this.diffNavigator.onDidUpdate(() => {
|
||||
this.diffNavigatorDisposables.push(this.diffNavigator);
|
||||
|
||||
this.diffNavigatorDisposables.push(this.diffNavigator.onDidUpdate(() => {
|
||||
this.nextDiffAction.updateEnablement();
|
||||
this.previousDiffAction.updateEnablement();
|
||||
});
|
||||
}));
|
||||
|
||||
this.updateIgnoreTrimWhitespaceAction();
|
||||
}, error => {
|
||||
|
||||
@@ -190,6 +199,26 @@ export class TextDiffEditor extends BaseTextEditor {
|
||||
});
|
||||
}
|
||||
|
||||
public supportsCenteredLayout(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
private restoreTextDiffEditorViewState(input: EditorInput): boolean {
|
||||
if (input instanceof DiffEditorInput) {
|
||||
const resource = this.toDiffEditorViewStateResource(input);
|
||||
if (resource) {
|
||||
const viewState = this.loadTextEditorViewState(resource);
|
||||
if (viewState) {
|
||||
this.getControl().restoreViewState(viewState);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private updateIgnoreTrimWhitespaceAction(): void {
|
||||
const ignoreTrimWhitespace = this.configurationService.getValue<boolean>(this.getResource(), 'diffEditor.ignoreTrimWhitespace');
|
||||
if (this.toggleIgnoreTrimWhitespaceAction) {
|
||||
@@ -278,9 +307,10 @@ export class TextDiffEditor extends BaseTextEditor {
|
||||
public clearInput(): void {
|
||||
|
||||
// Dispose previous diff navigator
|
||||
if (this.diffNavigator) {
|
||||
this.diffNavigator.dispose();
|
||||
}
|
||||
this.diffNavigatorDisposables = dispose(this.diffNavigatorDisposables);
|
||||
|
||||
// Keep editor view state in settings to restore when coming back
|
||||
this.saveTextDiffEditorViewState(this.input);
|
||||
|
||||
// Clear Model
|
||||
this.getControl().setModel(null);
|
||||
@@ -305,14 +335,85 @@ export class TextDiffEditor extends BaseTextEditor {
|
||||
return super.getControl() as IDiffEditor;
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
protected loadTextEditorViewState(resource: URI): IDiffEditorViewState {
|
||||
return super.loadTextEditorViewState(resource) as IDiffEditorViewState; // overridden for text diff editor support
|
||||
}
|
||||
|
||||
// Dispose previous diff navigator
|
||||
if (this.diffNavigator) {
|
||||
this.diffNavigator.dispose();
|
||||
private saveTextDiffEditorViewState(input: EditorInput): void {
|
||||
if (!(input instanceof DiffEditorInput)) {
|
||||
return; // only supported for diff editor inputs
|
||||
}
|
||||
|
||||
this._configurationListener.dispose();
|
||||
const resource = this.toDiffEditorViewStateResource(input);
|
||||
if (!resource) {
|
||||
return; // unable to retrieve input resource
|
||||
}
|
||||
|
||||
// Clear view state if input is disposed
|
||||
if (input.isDisposed()) {
|
||||
super.clearTextEditorViewState([resource]);
|
||||
}
|
||||
|
||||
// Otherwise save it
|
||||
else {
|
||||
super.saveTextEditorViewState(resource);
|
||||
|
||||
// Make sure to clean up when the input gets disposed
|
||||
once(input.onDispose)(() => {
|
||||
super.clearTextEditorViewState([resource]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected retrieveTextEditorViewState(resource: URI): IDiffEditorViewState {
|
||||
return this.retrieveTextDiffEditorViewState(resource); // overridden for text diff editor support
|
||||
}
|
||||
|
||||
private retrieveTextDiffEditorViewState(resource: URI): IDiffEditorViewState {
|
||||
const editor = getCodeOrDiffEditor(this).diffEditor;
|
||||
if (!editor) {
|
||||
return null; // not supported for non-diff editors
|
||||
}
|
||||
|
||||
const model = editor.getModel();
|
||||
if (!model || !model.modified || !model.original) {
|
||||
return null; // view state always needs a model
|
||||
}
|
||||
|
||||
const modelUri = this.toDiffEditorViewStateResource(model);
|
||||
if (!modelUri) {
|
||||
return null; // model URI is needed to make sure we save the view state correctly
|
||||
}
|
||||
|
||||
if (modelUri.toString() !== resource.toString()) {
|
||||
return null; // prevent saving view state for a model that is not the expected one
|
||||
}
|
||||
|
||||
return editor.saveViewState();
|
||||
}
|
||||
|
||||
private toDiffEditorViewStateResource(modelOrInput: IDiffEditorModel | DiffEditorInput): URI {
|
||||
let original: URI;
|
||||
let modified: URI;
|
||||
|
||||
if (modelOrInput instanceof DiffEditorInput) {
|
||||
original = modelOrInput.originalInput.getResource();
|
||||
modified = modelOrInput.modifiedInput.getResource();
|
||||
} else {
|
||||
original = modelOrInput.original.uri;
|
||||
modified = modelOrInput.modified.uri;
|
||||
}
|
||||
|
||||
if (!original || !modified) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// create a URI that is the Base64 concatenation of original + modified resource
|
||||
return URI.from({ scheme: 'diff', path: `${btoa(original.toString())}${btoa(modified.toString())}` });
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.diffNavigatorDisposables = dispose(this.diffNavigatorDisposables);
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
@@ -372,4 +473,4 @@ class ToggleIgnoreTrimWhitespaceAction extends Action {
|
||||
this._configurationService.updateValue(`diffEditor.ignoreTrimWhitespace`, !this._isChecked);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,16 +5,15 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
import nls = require('vs/nls');
|
||||
import * as nls from 'vs/nls';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { Dimension, Builder } from 'vs/base/browser/builder';
|
||||
import objects = require('vs/base/common/objects');
|
||||
import types = require('vs/base/common/types');
|
||||
import errors = require('vs/base/common/errors');
|
||||
import DOM = require('vs/base/browser/dom');
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
import * as types from 'vs/base/common/types';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { CodeEditor } from 'vs/editor/browser/codeEditor';
|
||||
import { EditorInput, EditorOptions } from 'vs/workbench/common/editor';
|
||||
import { EditorInput, EditorOptions, EditorViewStateMemento } from 'vs/workbench/common/editor';
|
||||
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
|
||||
import { IEditorViewState, IEditor } from 'vs/editor/common/editorCommon';
|
||||
import { Position } from 'vs/platform/editor/common/editor';
|
||||
@@ -43,15 +42,16 @@ export interface IEditorConfiguration {
|
||||
*/
|
||||
export abstract class BaseTextEditor extends BaseEditor {
|
||||
private editorControl: IEditor;
|
||||
private _editorContainer: Builder;
|
||||
private _editorContainer: HTMLElement;
|
||||
private hasPendingConfigurationChange: boolean;
|
||||
private lastAppliedEditorOptions: IEditorOptions;
|
||||
private editorViewStateMemento: EditorViewStateMemento<IEditorViewState>;
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
@IStorageService private storageService: IStorageService,
|
||||
@IStorageService storageService: IStorageService,
|
||||
@ITextResourceConfigurationService private readonly _configurationService: ITextResourceConfigurationService,
|
||||
@IThemeService protected themeService: IThemeService,
|
||||
@ITextFileService private readonly _textFileService: ITextFileService,
|
||||
@@ -59,6 +59,8 @@ export abstract class BaseTextEditor extends BaseEditor {
|
||||
) {
|
||||
super(id, telemetryService, themeService);
|
||||
|
||||
this.editorViewStateMemento = new EditorViewStateMemento<IEditorViewState>(this.getMemento(storageService, Scope.WORKSPACE), TEXT_EDITOR_VIEW_STATE_PREFERENCE_KEY, 100);
|
||||
|
||||
this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.handleConfigurationChangeEvent(this.configurationService.getValue<IEditorConfiguration>(this.getResource()))));
|
||||
}
|
||||
|
||||
@@ -123,7 +125,7 @@ export abstract class BaseTextEditor extends BaseEditor {
|
||||
return overrides;
|
||||
}
|
||||
|
||||
protected createEditor(parent: Builder): void {
|
||||
protected createEditor(parent: HTMLElement): void {
|
||||
|
||||
// Editor for Text
|
||||
this._editorContainer = parent;
|
||||
@@ -177,10 +179,10 @@ export abstract class BaseTextEditor extends BaseEditor {
|
||||
*
|
||||
* The passed in configuration object should be passed to the editor control when creating it.
|
||||
*/
|
||||
protected createEditorControl(parent: Builder, configuration: IEditorOptions): IEditor {
|
||||
protected createEditorControl(parent: HTMLElement, configuration: IEditorOptions): IEditor {
|
||||
|
||||
// Use a getter for the instantiation service since some subclasses might use scoped instantiation services
|
||||
return this.instantiationService.createInstance(CodeEditor, parent.getHTMLElement(), configuration);
|
||||
return this.instantiationService.createInstance(CodeEditor, parent, configuration);
|
||||
}
|
||||
|
||||
public setInput(input: EditorInput, options?: EditorOptions): TPromise<void> {
|
||||
@@ -189,7 +191,7 @@ export abstract class BaseTextEditor extends BaseEditor {
|
||||
// Update editor options after having set the input. We do this because there can be
|
||||
// editor input specific options (e.g. an ARIA label depending on the input showing)
|
||||
this.updateEditorConfiguration();
|
||||
this._editorContainer.getHTMLElement().setAttribute('aria-label', this.computeAriaLabel());
|
||||
this._editorContainer.setAttribute('aria-label', this.computeAriaLabel());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -219,7 +221,7 @@ export abstract class BaseTextEditor extends BaseEditor {
|
||||
this.editorControl.focus();
|
||||
}
|
||||
|
||||
public layout(dimension: Dimension): void {
|
||||
public layout(dimension: DOM.Dimension): void {
|
||||
|
||||
// Pass on to Editor
|
||||
this.editorControl.layout(dimension);
|
||||
@@ -233,69 +235,51 @@ export abstract class BaseTextEditor extends BaseEditor {
|
||||
* Saves the text editor view state for the given resource.
|
||||
*/
|
||||
protected saveTextEditorViewState(resource: URI): void {
|
||||
const editorViewState = this.retrieveTextEditorViewState(resource);
|
||||
if (!editorViewState) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.editorViewStateMemento.saveState(resource, this.position, editorViewState);
|
||||
}
|
||||
|
||||
protected retrieveTextEditorViewState(resource: URI): IEditorViewState {
|
||||
const editor = getCodeOrDiffEditor(this).codeEditor;
|
||||
if (!editor) {
|
||||
return; // not supported for diff editors
|
||||
return null; // not supported for diff editors
|
||||
}
|
||||
|
||||
const model = editor.getModel();
|
||||
if (!model) {
|
||||
return; // view state always needs a model
|
||||
return null; // view state always needs a model
|
||||
}
|
||||
|
||||
const modelUri = model.uri;
|
||||
if (!modelUri) {
|
||||
return; // model URI is needed to make sure we save the view state correctly
|
||||
return null; // model URI is needed to make sure we save the view state correctly
|
||||
}
|
||||
|
||||
if (modelUri.toString() !== resource.toString()) {
|
||||
return; // prevent saving view state for a model that is not the expected one
|
||||
return null; // prevent saving view state for a model that is not the expected one
|
||||
}
|
||||
|
||||
const memento = this.getMemento(this.storageService, Scope.WORKSPACE);
|
||||
|
||||
let textEditorViewStateMemento: { [key: string]: { [position: number]: IEditorViewState } } = memento[TEXT_EDITOR_VIEW_STATE_PREFERENCE_KEY];
|
||||
if (!textEditorViewStateMemento) {
|
||||
textEditorViewStateMemento = Object.create(null);
|
||||
memento[TEXT_EDITOR_VIEW_STATE_PREFERENCE_KEY] = textEditorViewStateMemento;
|
||||
}
|
||||
|
||||
let lastKnownViewState = textEditorViewStateMemento[resource.toString()];
|
||||
if (!lastKnownViewState) {
|
||||
lastKnownViewState = Object.create(null);
|
||||
textEditorViewStateMemento[resource.toString()] = lastKnownViewState;
|
||||
}
|
||||
|
||||
if (typeof this.position === 'number') {
|
||||
lastKnownViewState[this.position] = editor.saveViewState();
|
||||
}
|
||||
return editor.saveViewState();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the text editor view state for the given resources.
|
||||
*/
|
||||
protected clearTextEditorViewState(resources: URI[]): void {
|
||||
const memento = this.getMemento(this.storageService, Scope.WORKSPACE);
|
||||
const textEditorViewStateMemento: { [key: string]: { [position: number]: IEditorViewState } } = memento[TEXT_EDITOR_VIEW_STATE_PREFERENCE_KEY];
|
||||
if (textEditorViewStateMemento) {
|
||||
resources.forEach(resource => delete textEditorViewStateMemento[resource.toString()]);
|
||||
}
|
||||
resources.forEach(resource => {
|
||||
this.editorViewStateMemento.clearState(resource);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the text editor view state for the given resource and returns it.
|
||||
*/
|
||||
protected loadTextEditorViewState(resource: URI): IEditorViewState {
|
||||
const memento = this.getMemento(this.storageService, Scope.WORKSPACE);
|
||||
const textEditorViewStateMemento: { [key: string]: { [position: number]: IEditorViewState } } = memento[TEXT_EDITOR_VIEW_STATE_PREFERENCE_KEY];
|
||||
if (textEditorViewStateMemento) {
|
||||
const viewState = textEditorViewStateMemento[resource.toString()];
|
||||
if (viewState) {
|
||||
return viewState[this.position];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return this.editorViewStateMemento.loadState(resource, this.position);
|
||||
}
|
||||
|
||||
private updateEditorConfiguration(configuration = this.configurationService.getValue<IEditorConfiguration>(this.getResource())): void {
|
||||
@@ -337,6 +321,14 @@ export abstract class BaseTextEditor extends BaseEditor {
|
||||
|
||||
protected abstract getAriaLabel(): string;
|
||||
|
||||
protected saveMemento(): void {
|
||||
|
||||
// ensure to first save our view state memento
|
||||
this.editorViewStateMemento.save();
|
||||
|
||||
super.saveMemento();
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.lastAppliedEditorOptions = void 0;
|
||||
this.editorControl.dispose();
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
'use strict';
|
||||
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import nls = require('vs/nls');
|
||||
import types = require('vs/base/common/types');
|
||||
import * as nls from 'vs/nls';
|
||||
import * as types from 'vs/base/common/types';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
|
||||
import { TextEditorOptions, EditorModel, EditorInput, EditorOptions } from 'vs/workbench/common/editor';
|
||||
@@ -67,7 +67,7 @@ export class AbstractTextResourceEditor extends BaseTextEditor {
|
||||
}
|
||||
|
||||
// Remember view settings if input changes
|
||||
this.saveTextEditorViewStateForInput(this.input);
|
||||
this.saveTextResourceEditorViewState(this.input);
|
||||
|
||||
// Set input and resolve
|
||||
return super.setInput(input, options).then(() => {
|
||||
@@ -97,7 +97,7 @@ export class AbstractTextResourceEditor extends BaseTextEditor {
|
||||
|
||||
// Otherwise restore View State
|
||||
if (!optionsGotApplied) {
|
||||
this.restoreViewState(input);
|
||||
this.restoreTextResourceEditorViewState(input);
|
||||
}
|
||||
|
||||
return void 0;
|
||||
@@ -105,7 +105,7 @@ export class AbstractTextResourceEditor extends BaseTextEditor {
|
||||
});
|
||||
}
|
||||
|
||||
protected restoreViewState(input: EditorInput) {
|
||||
private restoreTextResourceEditorViewState(input: EditorInput) {
|
||||
if (input instanceof UntitledEditorInput || input instanceof ResourceEditorInput) {
|
||||
const viewState = this.loadTextEditorViewState(input.getResource());
|
||||
if (viewState) {
|
||||
@@ -153,7 +153,7 @@ export class AbstractTextResourceEditor extends BaseTextEditor {
|
||||
public clearInput(): void {
|
||||
|
||||
// Keep editor view state in settings to restore when coming back
|
||||
this.saveTextEditorViewStateForInput(this.input);
|
||||
this.saveTextResourceEditorViewState(this.input);
|
||||
|
||||
// Clear Model
|
||||
this.getControl().setModel(null);
|
||||
@@ -165,14 +165,14 @@ export class AbstractTextResourceEditor extends BaseTextEditor {
|
||||
|
||||
// Save View State (only for untitled)
|
||||
if (this.input instanceof UntitledEditorInput) {
|
||||
this.saveTextEditorViewStateForInput(this.input);
|
||||
this.saveTextResourceEditorViewState(this.input);
|
||||
}
|
||||
|
||||
// Call Super
|
||||
super.shutdown();
|
||||
}
|
||||
|
||||
protected saveTextEditorViewStateForInput(input: EditorInput): void {
|
||||
private saveTextResourceEditorViewState(input: EditorInput): void {
|
||||
if (!(input instanceof UntitledEditorInput) && !(input instanceof ResourceEditorInput)) {
|
||||
return; // only enabled for untitled and resource inputs
|
||||
}
|
||||
|
||||
@@ -6,15 +6,14 @@
|
||||
'use strict';
|
||||
|
||||
import 'vs/css!./media/titlecontrol';
|
||||
import nls = require('vs/nls');
|
||||
import * as nls from 'vs/nls';
|
||||
import { prepareActions } from 'vs/workbench/browser/actions';
|
||||
import { IAction, Action, IRunEvent } from 'vs/base/common/actions';
|
||||
import errors = require('vs/base/common/errors');
|
||||
import DOM = require('vs/base/browser/dom');
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
import arrays = require('vs/base/common/arrays');
|
||||
import * as arrays from 'vs/base/common/arrays';
|
||||
import { IEditorStacksModel, IEditorGroup, IEditorIdentifier, EditorInput, IStacksModelChangeEvent, toResource, IEditorCommandsContext } from 'vs/workbench/common/editor';
|
||||
import { IActionItem, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar';
|
||||
@@ -28,7 +27,7 @@ import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { ResolvedKeybinding } from 'vs/base/common/keyCodes';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { SplitEditorAction, CloseEditorAction } from 'vs/workbench/browser/parts/editor/editorActions';
|
||||
import { SplitEditorAction, CloseOneEditorAction } from 'vs/workbench/browser/parts/editor/editorActions';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { createActionItem, fillInActions } from 'vs/platform/actions/browser/menuItemActionItem';
|
||||
import { IMenuService, MenuId, IMenu, ExecuteCommandAction } from 'vs/platform/actions/common/actions';
|
||||
@@ -36,8 +35,8 @@ import { ResourceContextKey } from 'vs/workbench/common/resources';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { Themable } from 'vs/workbench/common/theme';
|
||||
import { isDiffEditor, isCodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { Dimension } from 'vs/base/browser/builder';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { Dimension, findParentWithClass } from 'vs/base/browser/dom';
|
||||
|
||||
export interface IToolbarActions {
|
||||
primary: IAction[];
|
||||
@@ -65,7 +64,7 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl
|
||||
|
||||
protected dragged: boolean;
|
||||
|
||||
protected closeEditorAction: CloseEditorAction;
|
||||
protected closeOneEditorAction: CloseOneEditorAction;
|
||||
protected splitEditorAction: SplitEditorAction;
|
||||
|
||||
private parent: HTMLElement;
|
||||
@@ -75,7 +74,8 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl
|
||||
protected editorActionsToolbar: ToolBar;
|
||||
|
||||
private mapActionsToEditors: { [editorId: string]: IToolbarActions; };
|
||||
private scheduler: RunOnceScheduler;
|
||||
private titleAreaUpdateScheduler: RunOnceScheduler;
|
||||
private titleAreaToolbarUpdateScheduler: RunOnceScheduler;
|
||||
private refreshScheduled: boolean;
|
||||
|
||||
private resourceContext: ResourceContextKey;
|
||||
@@ -101,8 +101,11 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl
|
||||
this.stacks = editorGroupService.getStacksModel();
|
||||
this.mapActionsToEditors = Object.create(null);
|
||||
|
||||
this.scheduler = new RunOnceScheduler(() => this.onSchedule(), 0);
|
||||
this.toUnbind.push(this.scheduler);
|
||||
this.titleAreaUpdateScheduler = new RunOnceScheduler(() => this.onSchedule(), 0);
|
||||
this.toUnbind.push(this.titleAreaUpdateScheduler);
|
||||
|
||||
this.titleAreaToolbarUpdateScheduler = new RunOnceScheduler(() => this.updateEditorActionsToolbar(), 0);
|
||||
this.toUnbind.push(this.titleAreaToolbarUpdateScheduler);
|
||||
|
||||
this.resourceContext = instantiationService.createInstance(ResourceContextKey);
|
||||
|
||||
@@ -166,22 +169,26 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl
|
||||
|
||||
public update(instant?: boolean): void {
|
||||
if (instant) {
|
||||
this.scheduler.cancel();
|
||||
this.titleAreaUpdateScheduler.cancel();
|
||||
this.onSchedule();
|
||||
} else {
|
||||
this.scheduler.schedule();
|
||||
this.titleAreaUpdateScheduler.schedule();
|
||||
}
|
||||
|
||||
this.titleAreaToolbarUpdateScheduler.cancel(); // a title area update will always refresh the toolbar too
|
||||
}
|
||||
|
||||
public refresh(instant?: boolean) {
|
||||
this.refreshScheduled = true;
|
||||
|
||||
if (instant) {
|
||||
this.scheduler.cancel();
|
||||
this.titleAreaUpdateScheduler.cancel();
|
||||
this.onSchedule();
|
||||
} else {
|
||||
this.scheduler.schedule();
|
||||
this.titleAreaUpdateScheduler.schedule();
|
||||
}
|
||||
|
||||
this.titleAreaToolbarUpdateScheduler.cancel(); // a title area update will always refresh the toolbar too
|
||||
}
|
||||
|
||||
public create(parent: HTMLElement): void {
|
||||
@@ -203,11 +210,11 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl
|
||||
}
|
||||
|
||||
public allowDragging(element: HTMLElement): boolean {
|
||||
return !DOM.findParentWithClass(element, 'monaco-action-bar', 'one-editor-silo');
|
||||
return !findParentWithClass(element, 'monaco-action-bar', 'one-editor-silo');
|
||||
}
|
||||
|
||||
protected initActions(services: IInstantiationService): void {
|
||||
this.closeEditorAction = services.createInstance(CloseEditorAction, CloseEditorAction.ID, nls.localize('close', "Close"));
|
||||
this.closeOneEditorAction = services.createInstance(CloseOneEditorAction, CloseOneEditorAction.ID, CloseOneEditorAction.LABEL);
|
||||
this.splitEditorAction = services.createInstance(SplitEditorAction, SplitEditorAction.ID, SplitEditorAction.LABEL);
|
||||
}
|
||||
|
||||
@@ -296,7 +303,14 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl
|
||||
const codeEditor = isCodeEditor(widget) && widget || isDiffEditor(widget) && widget.getModifiedEditor();
|
||||
const scopedContextKeyService = codeEditor && codeEditor.invokeWithinContext(accessor => accessor.get(IContextKeyService)) || this.contextKeyService;
|
||||
const titleBarMenu = this.menuService.createMenu(MenuId.EditorTitle, scopedContextKeyService);
|
||||
this.disposeOnEditorActions.push(titleBarMenu, titleBarMenu.onDidChange(_ => this.update()));
|
||||
this.disposeOnEditorActions.push(titleBarMenu, titleBarMenu.onDidChange(_ => {
|
||||
// schedule the update for the title area toolbar only if no other
|
||||
// update to the title area is scheduled which will always also
|
||||
// update the toolbar
|
||||
if (!this.titleAreaUpdateScheduler.isScheduled()) {
|
||||
this.titleAreaToolbarUpdateScheduler.schedule();
|
||||
}
|
||||
}));
|
||||
|
||||
fillInActions(titleBarMenu, { arg: this.resourceContext.get(), shouldForwardArgs: true }, { primary, secondary }, this.contextMenuService);
|
||||
}
|
||||
@@ -334,11 +348,10 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl
|
||||
|
||||
const primaryEditorActionIds = primaryEditorActions.map(a => a.id);
|
||||
if (!tabOptions.showTabs) {
|
||||
primaryEditorActionIds.push(this.closeEditorAction.id); // always show "Close" when tabs are disabled
|
||||
primaryEditorActionIds.push(this.closeOneEditorAction.id); // always show "Close" when tabs are disabled
|
||||
}
|
||||
|
||||
const secondaryEditorActionIds = secondaryEditorActions.map(a => a.id);
|
||||
|
||||
if (
|
||||
!arrays.equals(primaryEditorActionIds, this.currentPrimaryEditorActionIds) ||
|
||||
!arrays.equals(secondaryEditorActionIds, this.currentSecondaryEditorActionIds) ||
|
||||
@@ -348,7 +361,7 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl
|
||||
this.editorActionsToolbar.setActions(primaryEditorActions, secondaryEditorActions)();
|
||||
|
||||
if (!tabOptions.showTabs) {
|
||||
this.editorActionsToolbar.addPrimaryAction(this.closeEditorAction)();
|
||||
this.editorActionsToolbar.addPrimaryAction(this.closeOneEditorAction)();
|
||||
}
|
||||
|
||||
this.currentPrimaryEditorActionIds = primaryEditorActionIds;
|
||||
@@ -416,7 +429,7 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl
|
||||
// Actions
|
||||
[
|
||||
this.splitEditorAction,
|
||||
this.closeEditorAction
|
||||
this.closeOneEditorAction
|
||||
].forEach((action) => {
|
||||
action.dispose();
|
||||
});
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { Scope } from 'vs/workbench/common/memento';
|
||||
|
||||
export interface HtmlPreviewEditorViewState {
|
||||
scrollYPercentage: number;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This class is only intended to be subclassed and not instantiated.
|
||||
*/
|
||||
export abstract class BaseWebviewEditor extends BaseEditor {
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
telemetryService: ITelemetryService,
|
||||
themeService: IThemeService,
|
||||
private storageService: IStorageService
|
||||
) {
|
||||
super(id, telemetryService, themeService);
|
||||
}
|
||||
|
||||
private get viewStateStorageKey(): string {
|
||||
return this.getId() + '.editorViewState';
|
||||
}
|
||||
|
||||
protected saveViewState(resource: URI | string, editorViewState: HtmlPreviewEditorViewState): void {
|
||||
const memento = this.getMemento(this.storageService, Scope.WORKSPACE);
|
||||
let editorViewStateMemento: { [key: string]: { [position: number]: HtmlPreviewEditorViewState } } = memento[this.viewStateStorageKey];
|
||||
if (!editorViewStateMemento) {
|
||||
editorViewStateMemento = Object.create(null);
|
||||
memento[this.viewStateStorageKey] = editorViewStateMemento;
|
||||
}
|
||||
|
||||
let fileViewState = editorViewStateMemento[resource.toString()];
|
||||
if (!fileViewState) {
|
||||
fileViewState = Object.create(null);
|
||||
editorViewStateMemento[resource.toString()] = fileViewState;
|
||||
}
|
||||
|
||||
if (typeof this.position === 'number') {
|
||||
fileViewState[this.position] = editorViewState;
|
||||
}
|
||||
}
|
||||
|
||||
protected loadViewState(resource: URI | string): HtmlPreviewEditorViewState | null {
|
||||
const memento = this.getMemento(this.storageService, Scope.WORKSPACE);
|
||||
const editorViewStateMemento: { [key: string]: { [position: number]: HtmlPreviewEditorViewState } } = memento[this.viewStateStorageKey];
|
||||
if (editorViewStateMemento) {
|
||||
const fileViewState = editorViewStateMemento[resource.toString()];
|
||||
if (fileViewState) {
|
||||
return fileViewState[this.position];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user