Make Pane.promptToSaveItem synchronous.

This commit is contained in:
Cheng Zhao
2013-06-27 12:40:36 +08:00
parent f45ce3a7ee
commit 6c0f4c09d9
5 changed files with 46 additions and 47 deletions

View File

@@ -154,7 +154,7 @@ describe "PaneContainer", ->
it "resolves the returned promise after modified files are saved", ->
pane1.itemAtIndex(0).isModified = -> true
pane2.itemAtIndex(0).isModified = -> true
spyOn(atom, "confirm").andCallFake (a, b, c, d, e, f, g, noSaveFn) -> noSaveFn()
spyOn(atom, "confirmSync").andReturn(0)
promiseHandler = jasmine.createSpy("promiseHandler")
failedPromiseHandler = jasmine.createSpy("failedPromiseHandler")
@@ -167,12 +167,12 @@ describe "PaneContainer", ->
runs ->
expect(failedPromiseHandler).not.toHaveBeenCalled()
expect(atom.confirm).toHaveBeenCalled()
expect(atom.confirmSync).toHaveBeenCalled()
it "rejects the returned promise if the user cancels saving", ->
pane1.itemAtIndex(0).isModified = -> true
pane2.itemAtIndex(0).isModified = -> true
spyOn(atom, "confirm").andCallFake (a, b, c, d, e, cancelFn, f, g) -> cancelFn()
spyOn(atom, "confirmSync").andReturn(1)
promiseHandler = jasmine.createSpy("promiseHandler")
failedPromiseHandler = jasmine.createSpy("failedPromiseHandler")
@@ -185,7 +185,7 @@ describe "PaneContainer", ->
runs ->
expect(promiseHandler).not.toHaveBeenCalled()
expect(atom.confirm).toHaveBeenCalled()
expect(atom.confirmSync).toHaveBeenCalled()
describe "serialization", ->
it "can be serialized and deserialized, and correctly adjusts dimensions of deserialized panes after attach", ->

View File

@@ -106,28 +106,17 @@ describe "Pane", ->
describe "if the item is modified", ->
beforeEach ->
spyOn(atom, 'confirm')
spyOn(atom, 'showSaveDialog')
spyOn(editSession2, 'save')
spyOn(editSession2, 'saveAs')
atom.confirm.selectOption = (buttonText) ->
for arg, i in @argsForCall[0] when arg is buttonText
@argsForCall[0][i + 1]?()
editSession2.insertText('a')
expect(editSession2.isModified()).toBeTruthy()
pane.destroyItem(editSession2)
it "presents a dialog with the option to save the item first", ->
expect(atom.confirm).toHaveBeenCalled()
expect(pane.getItems().indexOf(editSession2)).not.toBe -1
expect(editSession2.destroyed).toBeFalsy()
describe "if the [Save] option is selected", ->
describe "when the item has a uri", ->
it "saves the item before removing and destroying it", ->
atom.confirm.selectOption('Save')
spyOn(atom, 'confirmSync').andReturn(0)
pane.destroyItem(editSession2)
expect(editSession2.save).toHaveBeenCalled()
expect(pane.getItems().indexOf(editSession2)).toBe -1
@@ -137,11 +126,11 @@ describe "Pane", ->
it "presents a save-as dialog, then saves the item with the given uri before removing and destroying it", ->
editSession2.buffer.setPath(undefined)
atom.confirm.selectOption('Save')
spyOn(atom, 'showSaveDialogSync').andReturn("/selected/path")
spyOn(atom, 'confirmSync').andReturn(0)
pane.destroyItem(editSession2)
expect(atom.showSaveDialog).toHaveBeenCalled()
atom.showSaveDialog.argsForCall[0][0]("/selected/path")
expect(atom.showSaveDialogSync).toHaveBeenCalled()
expect(editSession2.saveAs).toHaveBeenCalledWith("/selected/path")
expect(pane.getItems().indexOf(editSession2)).toBe -1
@@ -149,7 +138,8 @@ describe "Pane", ->
describe "if the [Don't Save] option is selected", ->
it "removes and destroys the item without saving it", ->
atom.confirm.selectOption("Don't Save")
spyOn(atom, 'confirmSync').andReturn(2)
pane.destroyItem(editSession2)
expect(editSession2.save).not.toHaveBeenCalled()
expect(pane.getItems().indexOf(editSession2)).toBe -1
@@ -157,7 +147,8 @@ describe "Pane", ->
describe "if the [Cancel] option is selected", ->
it "does not save, remove, or destroy the item", ->
atom.confirm.selectOption("Cancel")
spyOn(atom, 'confirmSync').andReturn(1)
pane.destroyItem(editSession2)
expect(editSession2.save).not.toHaveBeenCalled()
expect(pane.getItems().indexOf(editSession2)).not.toBe -1
@@ -309,7 +300,7 @@ describe "Pane", ->
describe "when the current item has no uri", ->
beforeEach ->
spyOn(atom, 'showSaveDialog')
spyOn(atom, 'showSaveDialogSync').andReturn('/selected/path')
describe "when the current item has a saveAs method", ->
it "opens a save dialog and saves the current item as the selected path", ->
@@ -319,19 +310,18 @@ describe "Pane", ->
pane.trigger 'core:save'
expect(atom.showSaveDialog).toHaveBeenCalled()
atom.showSaveDialog.argsForCall[0][0]('/selected/path')
expect(atom.showSaveDialogSync).toHaveBeenCalled()
expect(editSession2.saveAs).toHaveBeenCalledWith('/selected/path')
describe "when the current item has no saveAs method", ->
it "does nothing", ->
expect(pane.activeItem.saveAs).toBeUndefined()
pane.trigger 'core:save'
expect(atom.showSaveDialog).not.toHaveBeenCalled()
expect(atom.showSaveDialogSync).not.toHaveBeenCalled()
describe "core:save-as", ->
beforeEach ->
spyOn(atom, 'showSaveDialog')
spyOn(atom, 'showSaveDialogSync').andReturn('/selected/path')
describe "when the current item has a saveAs method", ->
it "opens the save dialog and calls saveAs on the item with the selected path", ->
@@ -340,15 +330,14 @@ describe "Pane", ->
pane.trigger 'core:save-as'
expect(atom.showSaveDialog).toHaveBeenCalled()
atom.showSaveDialog.argsForCall[0][0]('/selected/path')
expect(atom.showSaveDialogSync).toHaveBeenCalled()
expect(editSession2.saveAs).toHaveBeenCalledWith('/selected/path')
describe "when the current item does not have a saveAs method", ->
it "does nothing", ->
expect(pane.activeItem.saveAs).toBeUndefined()
pane.trigger 'core:save-as'
expect(atom.showSaveDialog).not.toHaveBeenCalled()
expect(atom.showSaveDialogSync).not.toHaveBeenCalled()
describe "pane:show-next-item and pane:show-previous-item", ->
it "advances forward/backward through the pane's items, looping around at either end", ->

View File

@@ -7,6 +7,7 @@ ipc = require 'ipc'
remote = require 'remote'
crypto = require 'crypto'
path = require 'path'
dialog = remote.require 'dialog'
window.atom =
loadedThemes: []
@@ -181,18 +182,22 @@ window.atom =
buttons.push buttonLabelsAndCallbacks.shift()
callbacks.push buttonLabelsAndCallbacks.shift()
chosen = remote.require('dialog').showMessageBox
chosen = confirmSync(message, detailedMessage, buttons)
callbacks[chosen]?()
confirmSync: (message, detailedMessage, buttons) ->
chosen = dialog.showMessageBox
type: 'info'
message: message
detail: detailedMessage
buttons: buttons
callbacks[chosen]?()
showSaveDialog: (callback) ->
callback(showSaveDialogSync())
showSaveDialogSync: ->
currentWindow = remote.getCurrentWindow()
result = remote.require('dialog').showSaveDialog currentWindow, title: 'Save File'
callback(result)
dialog.showSaveDialog currentWindow, title: 'Save File'
openDevTools: ->
remote.getCurrentWindow().openDevTools()

View File

@@ -91,7 +91,10 @@ class PaneContainer extends View
deferred.resolve()
else
item = modifiedItems.pop()
@paneAtIndex(0).promptToSaveItem item, saveNextModifiedItem, cancel
if @paneAtIndex(0).promptToSaveItem item
saveNextModifiedItem()
else
cancel()
saveNextModifiedItem()
deferred.promise()

View File

@@ -154,7 +154,7 @@ class Pane extends View
@autosaveItem(item)
if item.shouldPromptToSave?()
@promptToSaveItem(item, reallyDestroyItem)
reallyDestroyItem() if @promptToSaveItem(item)
else
reallyDestroyItem()
@@ -164,15 +164,17 @@ class Pane extends View
destroyInactiveItems: ->
@destroyItem(item) for item in @getItems() when item isnt @activeItem
promptToSaveItem: (item, nextAction, cancelAction) ->
promptToSaveItem: (item) ->
uri = item.getUri()
atom.confirm(
chosen = atom.confirmSync(
"'#{item.getTitle?() ? item.getUri()}' has changes, do you want to save them?"
"Your changes will be lost if you close this item without saving."
"Save", => @saveItem(item, nextAction)
"Cancel", cancelAction
"Don't Save", nextAction
["Save", "Cancel", "Don't Save"]
)
switch chosen
when 0 then @saveItem(item, -> true)
when 1 then false
when 2 then true
saveActiveItem: =>
@saveItem(@activeItem)
@@ -189,10 +191,10 @@ class Pane extends View
saveItemAs: (item, nextAction) ->
return unless item.saveAs?
atom.showSaveDialog (path) =>
if path
item.saveAs(path)
nextAction?()
path = atom.showSaveDialogSync()
if path
item.saveAs(path)
nextAction?()
saveItems: =>
@saveItem(item) for item in @getItems()