提交 93773614 编写于 作者: B Benjamin Pasero

first cut of handling dirty editors on close

上级 90186406
......@@ -23,7 +23,7 @@ import {Scope} from 'vs/workbench/browser/actionBarRegistry';
import {Part} from 'vs/workbench/browser/part';
import {EventType as WorkbenchEventType, EditorInputEvent, EditorEvent} from 'vs/workbench/common/events';
import {IEditorRegistry, Extensions as EditorExtensions, BaseEditor, EditorDescriptor} from 'vs/workbench/browser/parts/editor/baseEditor';
import {EditorInput, EditorOptions, TextEditorOptions} from 'vs/workbench/common/editor';
import {EditorInput, EditorOptions, TextEditorOptions, ConfirmResult} from 'vs/workbench/common/editor';
import {BaseTextEditor} from 'vs/workbench/browser/parts/editor/textEditor';
import {SideBySideEditorControl, Rochade, ISideBySideEditorControl, ProgressState, ITitleAreaState} from 'vs/workbench/browser/parts/editor/sideBySideEditorControl';
import {WorkbenchProgressService} from 'vs/workbench/services/progress/browser/progressService';
......@@ -467,6 +467,7 @@ export class EditorPart extends Part implements IEditorPart {
this.sideBySideControl.updateProgress(position, ProgressState.DONE);
// Event
this.emit(WorkbenchEventType.EDITOR_SET_INPUT_ERROR, new EditorEvent(editor, editor.getId(), input, options, position));
// Recover from this error by closing the editor if the attempt of setInput failed and we are not having any previous input
......@@ -503,11 +504,18 @@ export class EditorPart extends Part implements IEditorPart {
}
// Closing inactive editor is just a model update
group.closeEditor(input);
this.doCloseInactiveEditor(input, position);
}
private doCloseActiveEditor(position: Position): TPromise<void> {
// Check for dirty and veto
const input = this.visibleInputs[position];
return this.handleDirty([input]).then(veto => {
if (veto) {
return;
}
// Update visible inputs for position
this.visibleInputs[position] = null;
......@@ -535,6 +543,21 @@ export class EditorPart extends Part implements IEditorPart {
// in case of an error, continue closing
return this.doCloseActiveEditor(position);
});
});
}
private doCloseInactiveEditor(input: EditorInput, position: Position): TPromise<void> {
// Check for dirty and veto
return this.handleDirty([input]).then(veto => {
if (veto) {
return;
}
// Closing inactive editor is just a model update
const group = this.groupAt(position);
group.closeEditor(input);
});
}
private doCloseGroup(position: Position): TPromise<void> {
......@@ -610,6 +633,19 @@ export class EditorPart extends Part implements IEditorPart {
const group = this.groupAt(position);
// Check for dirty and veto
let editorsToClose: EditorInput[];
if (!direction) {
editorsToClose = group.getEditors().filter(e => !except || !e.matches(except));
} else {
editorsToClose = (direction === Direction.LEFT) ? group.getEditors().slice(0, group.indexOf(except)) : group.getEditors().slice(group.indexOf(except) + 1);
}
return this.handleDirty(editorsToClose).then(veto => {
if (veto) {
return;
}
// Close all editors in group
if (!except) {
......@@ -635,6 +671,7 @@ export class EditorPart extends Part implements IEditorPart {
return this.openEditor(except, null, position).then(() => {
return this.closeEditors(position, except, direction);
});
});
}
public closeAllEditors(except?: Position): TPromise<void> {
......@@ -648,6 +685,38 @@ export class EditorPart extends Part implements IEditorPart {
return TPromise.join(editors.map(e => this.closeEditors(e.position))).then(() => void 0);
}
private handleDirty(inputs: EditorInput[]): TPromise<boolean /* veto */> {
if (!inputs.length) {
return TPromise.as(false); // no veto
}
return this.doHandleDirty(inputs.shift()).then(veto => {
if (veto) {
return veto;
}
return this.handleDirty(inputs);
});
}
private doHandleDirty(input: EditorInput): TPromise<boolean /* veto */> {
if (!input || !input.isDirty()) {
return TPromise.as(false); // no veto
}
const res = input.confirmSave();
switch (res) {
case ConfirmResult.SAVE:
return input.save().then(ok => !ok);
case ConfirmResult.DONT_SAVE:
return input.revert().then(ok => !ok);
case ConfirmResult.CANCEL:
return TPromise.as(true); // veto
}
}
public getStacksModel(): EditorStacksModel {
return this.stacksModel;
}
......@@ -902,11 +971,21 @@ export class EditorPart extends Part implements IEditorPart {
return;
}
let closeActivePromise: TPromise<void> = TPromise.as(null);
// Unpinning an editor closes the preview editor if we have any
let handlePreviewEditor: TPromise<boolean> = TPromise.as(false);
if (group.previewEditor) {
handlePreviewEditor = this.handleDirty([group.previewEditor]);
}
handlePreviewEditor.done(veto => {
if (veto) {
return;
}
// The active editor is the preview editor and we are asked to make
// another editor the preview editor. So we need to take care of closing
// the active editor first
let closeActivePromise: TPromise<void> = TPromise.as(null);
if (group.isPreview(group.activeEditor) && !group.activeEditor.matches(input)) {
closeActivePromise = this.doCloseActiveEditor(position);
}
......@@ -920,6 +999,7 @@ export class EditorPart extends Part implements IEditorPart {
this.sideBySideControl.updateTitleArea({ position, preview: group.previewEditor });
}, errors.onUnexpectedError);
});
}
}
......
......@@ -38,6 +38,12 @@ export interface IInputStatus {
decoration?: string;
}
export enum ConfirmResult {
SAVE,
DONT_SAVE,
CANCEL
}
/**
* Editor inputs are lightweight objects that can be passed to the workbench API to open inside the editor part.
* Each editor input is mapped to an editor that is capable of opening it through the Platform facade.
......@@ -103,6 +109,40 @@ export abstract class EditorInput extends EventEmitter implements IEditorInput {
*/
public abstract resolve(refresh?: boolean): TPromise<EditorModel>;
/**
* An editor that is dirty will be asked to be saved once it closes.
*/
public isDirty(): boolean {
return false;
}
/**
* Subclasses should bring up a proper dialog for the user if the editor is dirty and return the result.
*/
public confirmSave(): ConfirmResult {
return ConfirmResult.DONT_SAVE;
}
/**
* Saves the editor if it is dirty. Subclasses return a promise with a boolean indicating the success of the operation.
*/
public save(): TPromise<boolean> {
return TPromise.as(true);
}
/**
* Reverts the editor if it is dirty. Subclasses return a promise with a boolean indicating the success of the operation.
*/
public revert(): TPromise<boolean> {
return TPromise.as(true);
}
/**
* Called when the editor is closed. Subclasses can free resources as needed.
*/
public close(): void {
}
/**
* Called when an editor input is no longer needed. Allows to free up any resources taken by
* resolving the editor input.
......@@ -222,6 +262,27 @@ export abstract class BaseDiffEditorInput extends EditorInput {
public getModifiedInput(): EditorInput {
return this.modifiedInput;
}
public isDirty(): boolean {
return this._modifiedInput.isDirty();
}
public confirmSave(): ConfirmResult {
return this._modifiedInput.confirmSave();
}
public save(): TPromise<boolean> {
return this._modifiedInput.save();
}
public revert(): TPromise<boolean> {
return this._modifiedInput.revert();
}
public close(): void {
this._originalInput.close();
this._modifiedInput.close();
}
}
/**
......
......@@ -317,6 +317,9 @@ export class EditorGroup implements IEditorGroup {
this.preview = null;
}
// Close it
editor.close();
// Remove from arrays
this.splice(index, true);
......
......@@ -9,13 +9,15 @@ import URI from 'vs/base/common/uri';
import {isUnspecific, guessMimeTypes, MIME_TEXT, suggestFilename} from 'vs/base/common/mime';
import labels = require('vs/base/common/labels');
import paths = require('vs/base/common/paths');
import {UntitledEditorInput as AbstractUntitledEditorInput, EditorModel, EncodingMode, IInputStatus} from 'vs/workbench/common/editor';
import {UntitledEditorInput as AbstractUntitledEditorInput, EditorModel, EncodingMode, IInputStatus, ConfirmResult} from 'vs/workbench/common/editor';
import {UntitledEditorModel} from 'vs/workbench/common/editor/untitledEditorModel';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {ILifecycleService} from 'vs/platform/lifecycle/common/lifecycle';
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
import {IModeService} from 'vs/editor/common/services/modeService';
import {ITextFileService} from 'vs/workbench/parts/files/common/files'; // TODO@Ben layer breaker
/**
* An editor input to be used for untitled text buffers.
*/
......@@ -36,7 +38,8 @@ export class UntitledEditorInput extends AbstractUntitledEditorInput {
@IInstantiationService private instantiationService: IInstantiationService,
@ILifecycleService private lifecycleService: ILifecycleService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IModeService private modeService: IModeService
@IModeService private modeService: IModeService,
@ITextFileService private textFileService: ITextFileService
) {
super();
......@@ -74,6 +77,18 @@ export class UntitledEditorInput extends AbstractUntitledEditorInput {
return null;
}
public confirmSave(): ConfirmResult {
return this.textFileService.confirmSave([this.resource]);
}
public save(): TPromise<boolean> {
return this.textFileService.save(this.resource);
}
public revert(): TPromise<boolean> {
return this.textFileService.revert(this.resource);
}
public suggestFileName(): string {
if (!this.hasAssociatedFilePath) {
let mime = this.getMime();
......
......@@ -14,7 +14,7 @@ import labels = require('vs/base/common/labels');
import URI from 'vs/base/common/uri';
import strings = require('vs/base/common/strings');
import assert = require('vs/base/common/assert');
import {EditorModel, IInputStatus, EncodingMode} from 'vs/workbench/common/editor';
import {EditorModel, IInputStatus, EncodingMode, ConfirmResult} from 'vs/workbench/common/editor';
import {IEditorRegistry, Extensions, EditorDescriptor} from 'vs/workbench/browser/parts/editor/baseEditor';
import {BinaryEditorModel} from 'vs/workbench/common/editor/binaryEditorModel';
import {IFileOperationResult, FileOperationResult} from 'vs/platform/files/common/files';
......@@ -175,6 +175,22 @@ export class FileEditorInput extends CommonFileEditorInput {
return null;
}
public isDirty(): boolean {
return this.textFileService.isDirty(this.resource);
}
public confirmSave(): ConfirmResult {
return this.textFileService.confirmSave([this.resource]);
}
public save(): TPromise<boolean> {
return this.textFileService.save(this.resource);
}
public revert(): TPromise<boolean> {
return this.textFileService.revert(this.resource);
}
public getPreferredEditorId(candidates: string[]): string {
let editorRegistry = (<IEditorRegistry>Registry.as(Extensions.Editors));
......
......@@ -25,10 +25,10 @@ import {MessageType, IInputValidator} from 'vs/base/browser/ui/inputbox/inputBox
import {ITree, IHighlightEvent} from 'vs/base/parts/tree/browser/tree';
import {dispose, IDisposable} from 'vs/base/common/lifecycle';
import {EventType as WorkbenchEventType, EditorEvent} from 'vs/workbench/common/events';
import Files = require('vs/workbench/parts/files/common/files');
import {LocalFileChangeEvent, VIEWLET_ID, ITextFileService, TextFileChangeEvent, ITextFileOperationResult, IWorkingFileModelChangeEvent, IWorkingFileEntry, IWorkingFilesModel, EventType as FileEventType} from 'vs/workbench/parts/files/common/files';
import {IFileService, IFileStat, IImportResult} from 'vs/platform/files/common/files';
import {DiffEditorInput, toDiffLabel} from 'vs/workbench/common/editor/diffEditorInput';
import {asFileEditorInput, getUntitledOrFileResource, TextEditorOptions, EditorOptions, UntitledEditorInput} from 'vs/workbench/common/editor';
import {asFileEditorInput, getUntitledOrFileResource, TextEditorOptions, EditorOptions, UntitledEditorInput, ConfirmResult} from 'vs/workbench/common/editor';
import {IEditorSelection} from 'vs/editor/common/editorCommon';
import {FileEditorInput} from 'vs/workbench/parts/files/browser/editors/fileEditorInput';
import {FileStat, NewStatPlaceholder} from 'vs/workbench/parts/files/common/explorerViewModel';
......@@ -50,8 +50,6 @@ import {IMessageService, IMessageWithAction, IConfirmation, Severity, CancelActi
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
import {KeyMod, KeyCode, Keybinding} from 'vs/base/common/keyCodes';
import ITextFileService = Files.ITextFileService;
export interface IEditableData {
action: IAction;
validator: IInputValidator;
......@@ -155,11 +153,11 @@ export class BaseFileAction extends Action {
protected handleDirty(): TPromise<boolean /* cancel */> {
if (this.textFileService.isDirty(this._element.resource)) {
let res = this.textFileService.confirmSave([this._element.resource]);
if (res === Files.ConfirmResult.SAVE) {
if (res === ConfirmResult.SAVE) {
return this.textFileService.save(this._element.resource).then(() => false);
}
if (res === Files.ConfirmResult.DONT_SAVE) {
if (res === ConfirmResult.DONT_SAVE) {
return this.textFileService.revert(this._element.resource).then(() => false);
}
......@@ -325,7 +323,7 @@ export abstract class BaseRenameAction extends BaseFileAction {
before = this.element.clone(); // Clone element to not expose viewers element to listeners
}
this.eventService.emit('files.internal:fileChanged', new Files.LocalFileChangeEvent(before, stat));
this.eventService.emit('files.internal:fileChanged', new LocalFileChangeEvent(before, stat));
}
}
......@@ -524,7 +522,7 @@ export abstract class BaseGlobalNewAction extends Action {
}
public run(): TPromise<any> {
return this.viewletService.openViewlet(Files.VIEWLET_ID, true).then((viewlet) => {
return this.viewletService.openViewlet(VIEWLET_ID, true).then((viewlet) => {
return TPromise.timeout(100).then(() => { // use a timeout to prevent the explorer from revealing the active file
viewlet.focus();
......@@ -730,7 +728,7 @@ export class BaseDeleteFileAction extends BaseFileAction {
// Since a delete operation can take a while we want to emit the event proactively to avoid issues
// with stale entries in the explorer tree.
this.eventService.emit('files.internal:fileChanged', new Files.LocalFileChangeEvent(this.element.clone(), null));
this.eventService.emit('files.internal:fileChanged', new LocalFileChangeEvent(this.element.clone(), null));
// Call function
let servicePromise = this.fileService.del(this.element.resource, this.useTrash).then(() => {
......@@ -748,7 +746,7 @@ export class BaseDeleteFileAction extends BaseFileAction {
this.onErrorWithRetry(error, () => this.run(), extraAction);
// Since the delete failed, best we can do is to refresh the explorer from the root to show the current state of files.
let event = new Files.LocalFileChangeEvent(new FileStat(this.contextService.getWorkspace().resource, true, true), new FileStat(this.contextService.getWorkspace().resource, true, true));
let event = new LocalFileChangeEvent(new FileStat(this.contextService.getWorkspace().resource, true, true), new FileStat(this.contextService.getWorkspace().resource, true, true));
this.eventService.emit('files.internal:fileChanged', event);
// Focus back to tree
......@@ -890,7 +888,7 @@ export class ImportFileAction extends BaseFileAction {
// Emit Deleted Event if file gets replaced unless it is the same file
let oldFile = targetNames[isLinux ? file.name : file.name.toLowerCase()];
if (oldFile && oldFile.resource.fsPath !== result.stat.resource.fsPath) {
this.eventService.emit('files.internal:fileChanged', new Files.LocalFileChangeEvent(oldFile, null));
this.eventService.emit('files.internal:fileChanged', new LocalFileChangeEvent(oldFile, null));
}
// Emit Import Event
......@@ -917,7 +915,7 @@ export class ImportFileAction extends BaseFileAction {
}
/** File import event is emitted when a file is import into the workbench. */
export class FileImportedEvent extends Files.LocalFileChangeEvent {
export class FileImportedEvent extends LocalFileChangeEvent {
private isNew: boolean;
constructor(stat?: IFileStat, isNew?: boolean, originalEvent?: Event) {
......@@ -1083,7 +1081,7 @@ export class DuplicateFileAction extends BaseFileAction {
// Copy File and emit event
let result = this.fileService.copyFile(this.element.resource, this.findTarget()).then((stat: IFileStat) => {
this.eventService.emit('files.internal:fileChanged', new Files.LocalFileChangeEvent(null, stat));
this.eventService.emit('files.internal:fileChanged', new LocalFileChangeEvent(null, stat));
}, (error: any) => {
this.onError(error);
});
......@@ -1544,10 +1542,10 @@ export abstract class BaseSaveAllAction extends BaseActionWithErrorReporting {
private registerListeners(): void {
// listen to files being changed locally
this.toDispose.push(this.eventService.addListener2(Files.EventType.FILE_DIRTY, (e: Files.TextFileChangeEvent) => this.updateEnablement(true)));
this.toDispose.push(this.eventService.addListener2(Files.EventType.FILE_SAVED, (e: Files.TextFileChangeEvent) => this.updateEnablement(false)));
this.toDispose.push(this.eventService.addListener2(Files.EventType.FILE_REVERTED, (e: Files.TextFileChangeEvent) => this.updateEnablement(false)));
this.toDispose.push(this.eventService.addListener2(Files.EventType.FILE_SAVE_ERROR, (e: Files.TextFileChangeEvent) => this.updateEnablement(true)));
this.toDispose.push(this.eventService.addListener2(FileEventType.FILE_DIRTY, (e: TextFileChangeEvent) => this.updateEnablement(true)));
this.toDispose.push(this.eventService.addListener2(FileEventType.FILE_SAVED, (e: TextFileChangeEvent) => this.updateEnablement(false)));
this.toDispose.push(this.eventService.addListener2(FileEventType.FILE_REVERTED, (e: TextFileChangeEvent) => this.updateEnablement(false)));
this.toDispose.push(this.eventService.addListener2(FileEventType.FILE_SAVE_ERROR, (e: TextFileChangeEvent) => this.updateEnablement(true)));
if (this.includeUntitled()) {
this.toDispose.push(this.eventService.addListener2(WorkbenchEventType.UNTITLED_FILE_DIRTY, () => this.updateEnablement(true)));
......@@ -1765,8 +1763,8 @@ export class ReopenClosedFileAction extends Action {
}
public run(): TPromise<any> {
let workingFilesModel: Files.IWorkingFilesModel = this.textFileService.getWorkingFilesModel();
let entry: Files.IWorkingFileEntry = workingFilesModel.popLastClosedEntry();
let workingFilesModel: IWorkingFilesModel = this.textFileService.getWorkingFilesModel();
let entry: IWorkingFileEntry = workingFilesModel.popLastClosedEntry();
if (entry === null) {
return TPromise.as(true);
......@@ -1825,12 +1823,12 @@ export abstract class BaseCloseWorkingFileAction extends Action {
isDirty = this.textFileService.isDirty();
}
let saveOrRevertPromise: TPromise<Files.ITextFileOperationResult> = TPromise.as(null);
let saveOrRevertPromise: TPromise<ITextFileOperationResult> = TPromise.as(null);
if (isDirty) {
let confirmResult = this.textFileService.confirmSave(this.elements);
switch (confirmResult) {
case Files.ConfirmResult.SAVE:
case ConfirmResult.SAVE:
if (this.elements) {
saveOrRevertPromise = this.textFileService.saveAll(this.elements);
} else {
......@@ -1838,7 +1836,7 @@ export abstract class BaseCloseWorkingFileAction extends Action {
}
break;
case Files.ConfirmResult.DONT_SAVE:
case ConfirmResult.DONT_SAVE:
if (this.elements) {
saveOrRevertPromise = this.textFileService.revertAll(this.elements);
} else {
......@@ -1846,12 +1844,12 @@ export abstract class BaseCloseWorkingFileAction extends Action {
}
break;
case Files.ConfirmResult.CANCEL:
case ConfirmResult.CANCEL:
return TPromise.as(null);
}
}
return saveOrRevertPromise.then((result?: Files.ITextFileOperationResult) => {
return saveOrRevertPromise.then((result?: ITextFileOperationResult) => {
// Collect resources to dispose
let resourcesToDispose: URI[] = [];
......@@ -1922,7 +1920,7 @@ export class CloseAllWorkingFilesAction extends BaseCloseWorkingFileAction {
return super.run().then(() => closeNonFileEditors(this.editorService)); // close non file editors too
}
private onModelChange(event: Files.IWorkingFileModelChangeEvent): void {
private onModelChange(event: IWorkingFileModelChangeEvent): void {
this.enabled = (this.model.count() > 0);
}
......@@ -2246,7 +2244,7 @@ export class FocusOpenEditorsView extends Action {
}
public run(): TPromise<any> {
return this.viewletService.openViewlet(Files.VIEWLET_ID, true).then((viewlet: ExplorerViewlet) => {
return this.viewletService.openViewlet(VIEWLET_ID, true).then((viewlet: ExplorerViewlet) => {
viewlet.getOpenEditorsView().expand();
viewlet.getOpenEditorsView().getViewer().DOMFocus();
});
......@@ -2267,7 +2265,7 @@ export class FocusFilesExplorer extends Action {
}
public run(): TPromise<any> {
return this.viewletService.openViewlet(Files.VIEWLET_ID, true).then((viewlet: ExplorerViewlet) => {
return this.viewletService.openViewlet(VIEWLET_ID, true).then((viewlet: ExplorerViewlet) => {
const view = viewlet.getExplorerView();
if (view) {
view.expand();
......@@ -2296,7 +2294,7 @@ export class ShowActiveFileInExplorer extends Action {
public run(): TPromise<any> {
let fileInput = asFileEditorInput(this.editorService.getActiveEditorInput(), true);
if (fileInput) {
return this.viewletService.openViewlet(Files.VIEWLET_ID, false).then((viewlet: ExplorerViewlet) => {
return this.viewletService.openViewlet(VIEWLET_ID, false).then((viewlet: ExplorerViewlet) => {
const isInsideWorkspace = this.contextService.isInsideWorkspace(fileInput.getResource());
if (isInsideWorkspace) {
const explorerView = viewlet.getExplorerView();
......
......@@ -11,8 +11,9 @@ import {ListenerUnbind} from 'vs/base/common/eventEmitter';
import Event, {Emitter} from 'vs/base/common/event';
import {FileEditorInput} from 'vs/workbench/parts/files/browser/editors/fileEditorInput';
import {CACHE, TextFileEditorModel} from 'vs/workbench/parts/files/common/editors/textFileEditorModel';
import {IResult, ITextFileOperationResult, ConfirmResult, ITextFileService, IAutoSaveConfiguration, AutoSaveMode} from 'vs/workbench/parts/files/common/files';
import {IResult, ITextFileOperationResult, ITextFileService, IAutoSaveConfiguration, AutoSaveMode} from 'vs/workbench/parts/files/common/files';
import {EventType} from 'vs/workbench/common/events';
import {ConfirmResult} from 'vs/workbench/common/editor';
import {WorkingFilesModel} from 'vs/workbench/parts/files/common/workingFilesModel';
import {IWorkspaceContextService} from 'vs/workbench/services/workspace/common/contextService';
import {IFilesConfiguration, IFileOperationResult, FileOperationResult, AutoSaveConfiguration} from 'vs/platform/files/common/files';
......
......@@ -22,11 +22,11 @@ import {$} from 'vs/base/browser/builder';
import platform = require('vs/base/common/platform');
import glob = require('vs/base/common/glob');
import {ContributableActionProvider} from 'vs/workbench/browser/actionBarRegistry';
import {LocalFileChangeEvent, ConfirmResult, IFilesConfiguration, ITextFileService} from 'vs/workbench/parts/files/common/files';
import {LocalFileChangeEvent, IFilesConfiguration, ITextFileService} from 'vs/workbench/parts/files/common/files';
import {IFileOperationResult, FileOperationResult, IFileStat, IFileService} from 'vs/platform/files/common/files';
import {FileEditorInput} from 'vs/workbench/parts/files/browser/editors/fileEditorInput';
import {DuplicateFileAction, ImportFileAction, PasteFileAction, keybindingForAction, IEditableData, IFileViewletState} from 'vs/workbench/parts/files/browser/fileActions';
import {EditorOptions} from 'vs/workbench/common/editor';
import {EditorOptions, ConfirmResult} from 'vs/workbench/common/editor';
import {IDataSource, ITree, IElementCallback, IAccessibilityProvider, IRenderer, ContextMenuEvent, ISorter, IFilter, IDragAndDrop, IDragAndDropData, IDragOverReaction, DRAG_OVER_ACCEPT_BUBBLE_DOWN, DRAG_OVER_ACCEPT_BUBBLE_DOWN_COPY, DRAG_OVER_ACCEPT_BUBBLE_UP, DRAG_OVER_ACCEPT_BUBBLE_UP_COPY, DRAG_OVER_REJECT} from 'vs/base/parts/tree/browser/tree';
import labels = require('vs/base/common/labels');
import {DesktopDragAndDropData, ExternalElementsDragAndDropData} from 'vs/base/parts/tree/browser/treeDnd';
......
......@@ -11,7 +11,7 @@ import Event from 'vs/base/common/event';
import {guessMimeTypes} from 'vs/base/common/mime';
import {IModel, IEditorOptions} from 'vs/editor/common/editorCommon';
import {IDisposable} from 'vs/base/common/lifecycle';
import {EncodingMode, EditorInput, IFileEditorInput} from 'vs/workbench/common/editor';
import {EncodingMode, EditorInput, IFileEditorInput, ConfirmResult} from 'vs/workbench/common/editor';
import {IFileStat, IFilesConfiguration} from 'vs/platform/files/common/files';
import {createDecorator, ServiceIdentifier} from 'vs/platform/instantiation/common/instantiation';
import {FileStat} from 'vs/workbench/parts/files/common/explorerViewModel';
......@@ -281,12 +281,6 @@ export class TextFileChangeEvent extends LocalFileChangeEvent {
export const TEXT_FILE_SERVICE_ID = 'textFileService';
export enum ConfirmResult {
SAVE,
DONT_SAVE,
CANCEL
}
export interface ITextFileOperationResult {
results: IResult[];
}
......
......@@ -12,10 +12,11 @@ import strings = require('vs/base/common/strings');
import {isWindows, isLinux} from 'vs/base/common/platform';
import URI from 'vs/base/common/uri';
import {UntitledEditorModel} from 'vs/workbench/common/editor/untitledEditorModel';
import {ConfirmResult} from 'vs/workbench/common/editor';
import {IEventService} from 'vs/platform/event/common/event';
import {TextFileService as AbstractTextFileService} from 'vs/workbench/parts/files/browser/textFileServices';
import {CACHE, TextFileEditorModel} from 'vs/workbench/parts/files/common/editors/textFileEditorModel';
import {ITextFileOperationResult, ConfirmResult, AutoSaveMode} from 'vs/workbench/parts/files/common/files';
import {ITextFileOperationResult, AutoSaveMode} from 'vs/workbench/parts/files/common/files';
import {IUntitledEditorService} from 'vs/workbench/services/untitled/common/untitledEditorService';
import {IFileService} from 'vs/platform/files/common/files';
import {BinaryEditorModel} from 'vs/workbench/common/editor/binaryEditorModel';
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册