提交 73e931d0 编写于 作者: B Benjamin Pasero

Save onFocusLost should only be triggered when whole editor widget looses focus (fixes #16659)

上级 2d1f793f
......@@ -24,6 +24,7 @@ import { IMessageService } from 'vs/platform/message/common/message';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IThemeService } from 'vs/workbench/services/themes/common/themeService';
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
/**
* An editor implementation that is capable of showing string inputs or promise inputs that resolve to a string.
......@@ -45,9 +46,10 @@ export class StringEditor extends BaseTextEditor {
@IEventService eventService: IEventService,
@IWorkbenchEditorService editorService: IWorkbenchEditorService,
@IThemeService themeService: IThemeService,
@IUntitledEditorService private untitledEditorService: IUntitledEditorService
@IUntitledEditorService private untitledEditorService: IUntitledEditorService,
@ITextFileService textFileService: ITextFileService
) {
super(StringEditor.ID, telemetryService, instantiationService, contextService, storageService, messageService, configurationService, eventService, editorService, themeService);
super(StringEditor.ID, telemetryService, instantiationService, contextService, storageService, messageService, configurationService, eventService, editorService, themeService, textFileService);
this.mapResourceToEditorViewState = Object.create(null);
......
......@@ -36,6 +36,7 @@ import { IMessageService } from 'vs/platform/message/common/message';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { RawContextKey, IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { IThemeService } from 'vs/workbench/services/themes/common/themeService';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
export const TextCompareEditorVisible = new RawContextKey<boolean>('textCompareEditorVisible', false);
......@@ -62,9 +63,10 @@ export class TextDiffEditor extends BaseTextEditor {
@IEventService eventService: IEventService,
@IWorkbenchEditorService editorService: IWorkbenchEditorService,
@IContextKeyService contextKeyService: IContextKeyService,
@IThemeService themeService: IThemeService
@IThemeService themeService: IThemeService,
@ITextFileService textFileService: ITextFileService
) {
super(TextDiffEditor.ID, telemetryService, instantiationService, contextService, storageService, messageService, configurationService, eventService, editorService, themeService);
super(TextDiffEditor.ID, telemetryService, instantiationService, contextService, storageService, messageService, configurationService, eventService, editorService, themeService, textFileService);
this.textDiffEditorVisible = TextCompareEditorVisible.bindTo(contextKeyService);
}
......
......@@ -8,11 +8,13 @@
import { TPromise } from 'vs/base/common/winjs.base';
import { Dimension, Builder } from 'vs/base/browser/builder';
import objects = require('vs/base/common/objects');
import errors = require('vs/base/common/errors');
import DOM = require('vs/base/browser/dom');
import { CodeEditor } from 'vs/editor/browser/codeEditor';
import { EditorInput, EditorOptions } from 'vs/workbench/common/editor';
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { EditorConfiguration } from 'vs/editor/common/config/commonEditorConfig';
import { IEditor, IEditorOptions } from 'vs/editor/common/editorCommon';
import { IEditor, IEditorOptions, EventType as EditorEventType } from 'vs/editor/common/editorCommon';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IFilesConfiguration } from 'vs/platform/files/common/files';
import { Position } from 'vs/platform/editor/common/editor';
......@@ -24,6 +26,8 @@ import { IMessageService } from 'vs/platform/message/common/message';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IThemeService } from 'vs/workbench/services/themes/common/themeService';
import { ITextFileService, SaveReason, AutoSaveMode } from 'vs/workbench/services/textfile/common/textfiles';
import { EventEmitter } from 'vs/base/common/eventEmitter';
/**
* The base class of editors that leverage the text editor for the editing experience. This class is only intended to
......@@ -33,6 +37,7 @@ export abstract class BaseTextEditor extends BaseEditor {
private editorControl: IEditor;
private _editorContainer: Builder;
private hasPendingConfigurationChange: boolean;
private pendingAutoSave: TPromise<void>;
constructor(
id: string,
......@@ -44,7 +49,8 @@ export abstract class BaseTextEditor extends BaseEditor {
@IConfigurationService private configurationService: IConfigurationService,
@IEventService private _eventService: IEventService,
@IWorkbenchEditorService private _editorService: IWorkbenchEditorService,
@IThemeService private themeService: IThemeService
@IThemeService private themeService: IThemeService,
@ITextFileService private textFileService: ITextFileService
) {
super(id, telemetryService);
......@@ -129,15 +135,55 @@ export abstract class BaseTextEditor extends BaseEditor {
this._editorContainer = parent;
this.editorControl = this.createEditorControl(parent);
// Application & Editor focus change
if (this.editorControl instanceof EventEmitter) {
this.toUnbind.push(this.editorControl.addListener2(EditorEventType.EditorBlur, () => this.onEditorFocusLost()));
}
this.toUnbind.push(DOM.addDisposableListener(window, DOM.EventType.BLUR, () => this.onWindowFocusLost()));
// Configuration
this.applyConfiguration(this.configurationService.getConfiguration<IFilesConfiguration>());
}
private onEditorFocusLost(): void {
if (this.pendingAutoSave) {
return; // save is already triggered
}
if (this.textFileService.getAutoSaveMode() === AutoSaveMode.ON_FOCUS_CHANGE && this.textFileService.isDirty()) {
this.saveAll(SaveReason.FOCUS_CHANGE);
}
}
private onWindowFocusLost(): void {
if (this.pendingAutoSave) {
return; // save is already triggered
}
if (this.textFileService.getAutoSaveMode() === AutoSaveMode.ON_WINDOW_CHANGE && this.textFileService.isDirty()) {
this.saveAll(SaveReason.WINDOW_CHANGE);
}
}
private saveAll(reason: SaveReason): void {
this.pendingAutoSave = this.textFileService.saveAll(void 0, reason).then(() => {
this.pendingAutoSave = void 0;
return void 0;
}, error => {
this.pendingAutoSave = void 0;
errors.onUnexpectedError(error);
return void 0;
});
}
/**
* This method creates and returns the text editor control to be used. Subclasses can override to
* provide their own editor control that should be used (e.g. a DiffEditor).
*/
public createEditorControl(parent: Builder): IEditor {
// Use a getter for the instantiation service since some subclasses might use scoped instantiation services
return this.instantiationService.createInstance(CodeEditor, parent.getHTMLElement(), this.getCodeEditorOptions());
}
......
......@@ -14,7 +14,7 @@ import { IEditorViewState, IEditorOptions } from 'vs/editor/common/editorCommon'
import { Action } from 'vs/base/common/actions';
import { Scope } from 'vs/workbench/common/memento';
import { VIEWLET_ID, TEXT_FILE_EDITOR_ID } from 'vs/workbench/parts/files/common/files';
import { ITextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles';
import { ITextFileEditorModel, ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { BaseTextEditor } from 'vs/workbench/browser/parts/editor/textEditor';
import { EditorOptions, TextEditorOptions } from 'vs/workbench/common/editor';
import { BinaryEditorModel } from 'vs/workbench/common/editor/binaryEditorModel';
......@@ -60,9 +60,10 @@ export class TextFileEditor extends BaseTextEditor {
@IConfigurationService configurationService: IConfigurationService,
@IEventService eventService: IEventService,
@IWorkbenchEditorService editorService: IWorkbenchEditorService,
@IThemeService themeService: IThemeService
@IThemeService themeService: IThemeService,
@ITextFileService textFileService: ITextFileService
) {
super(TextFileEditor.ID, telemetryService, instantiationService, contextService, storageService, messageService, configurationService, eventService, editorService, themeService);
super(TextFileEditor.ID, telemetryService, instantiationService, contextService, storageService, messageService, configurationService, eventService, editorService, themeService, textFileService);
// Clear view state for deleted files
this.toUnbind.push(this.eventService.addListener2(EventType.FILE_CHANGES, (e: FileChangesEvent) => this.onFilesChanged(e)));
......
......@@ -27,6 +27,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IThemeService } from 'vs/workbench/services/themes/common/themeService';
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
export class OutputPanel extends StringEditor {
......@@ -46,10 +47,11 @@ export class OutputPanel extends StringEditor {
@IThemeService themeService: IThemeService,
@IOutputService private outputService: IOutputService,
@IUntitledEditorService untitledEditorService: IUntitledEditorService,
@IContextKeyService private contextKeyService: IContextKeyService
@IContextKeyService private contextKeyService: IContextKeyService,
@ITextFileService textFileService: ITextFileService
) {
super(telemetryService, instantiationService, contextService, storageService,
messageService, configurationService, eventService, editorService, themeService, untitledEditorService);
messageService, configurationService, eventService, editorService, themeService, untitledEditorService, textFileService);
this.scopedInstantiationService = instantiationService;
this.toDispose = [];
}
......
......@@ -43,6 +43,7 @@ import { IModelService } from 'vs/editor/common/services/modelService';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IEventService } from 'vs/platform/event/common/event';
import { IMessageService } from 'vs/platform/message/common/message';
......@@ -119,9 +120,10 @@ export class DefaultPreferencesEditor extends BaseTextEditor {
@IUntitledEditorService private untitledEditorService: IUntitledEditorService,
@IPreferencesService private preferencesService: IPreferencesService,
@IModelService private modelService: IModelService,
@IModeService private modeService: IModeService
@IModeService private modeService: IModeService,
@ITextFileService textFileService: ITextFileService
) {
super(DefaultPreferencesEditor.ID, telemetryService, instantiationService, contextService, storageService, messageService, configurationService, eventService, editorService, themeService);
super(DefaultPreferencesEditor.ID, telemetryService, instantiationService, contextService, storageService, messageService, configurationService, eventService, editorService, themeService, textFileService);
this.delayedFilterLogging = new Delayer<void>(1000);
}
......
......@@ -8,7 +8,6 @@ import * as nls from 'vs/nls';
import { TPromise } from 'vs/base/common/winjs.base';
import URI from 'vs/base/common/uri';
import paths = require('vs/base/common/paths');
import DOM = require('vs/base/browser/dom');
import errors = require('vs/base/common/errors');
import objects = require('vs/base/common/objects');
import Event, { Emitter } from 'vs/base/common/event';
......@@ -108,11 +107,6 @@ export abstract class TextFileService implements ITextFileService {
// Configuration changes
this.toUnbind.push(this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationChange(e.config)));
// Application & Editor focus change
this.toUnbind.push(DOM.addDisposableListener(window, DOM.EventType.BLUR, () => this.onWindowFocusLost()));
this.toUnbind.push(DOM.addDisposableListener(window, DOM.EventType.BLUR, () => this.onEditorFocusChanged(), true));
this.toUnbind.push(this.editorGroupService.onEditorsChanged(() => this.onEditorFocusChanged()));
}
private beforeShutdown(reason: ShutdownReason): boolean | TPromise<boolean> {
......@@ -197,18 +191,6 @@ export abstract class TextFileService implements ITextFileService {
return this.backupService.cleanupBackupsBeforeShutdown().then(() => false, () => false);
}
private onWindowFocusLost(): void {
if (this.configuredAutoSaveOnWindowChange && this.isDirty()) {
this.saveAll(void 0, SaveReason.WINDOW_CHANGE).done(null, errors.onUnexpectedError);
}
}
private onEditorFocusChanged(): void {
if (this.configuredAutoSaveOnFocusChange && this.isDirty()) {
this.saveAll(void 0, SaveReason.FOCUS_CHANGE).done(null, errors.onUnexpectedError);
}
}
private onConfigurationChange(configuration: IFilesConfiguration): void {
const wasAutoSaveEnabled = (this.getAutoSaveMode() !== AutoSaveMode.OFF);
......
......@@ -298,8 +298,8 @@ export interface ITextFileService extends IDisposable {
* @param resources can be null to save all.
* @param includeUntitled to save all resources and optionally exclude untitled ones.
*/
saveAll(includeUntitled?: boolean): TPromise<ITextFileOperationResult>;
saveAll(resources: URI[]): TPromise<ITextFileOperationResult>;
saveAll(includeUntitled?: boolean, reason?: SaveReason): TPromise<ITextFileOperationResult>;
saveAll(resources: URI[], reason?: SaveReason): TPromise<ITextFileOperationResult>;
/**
* Reverts the provided resource.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册