mirror of
https://github.com/atom/atom.git
synced 2026-01-23 13:58:08 -05:00
Add restoreItem to Pane container
This commit is contained in:
committed by
probablycorey
parent
96fefe94f0
commit
5ad53bb32c
@@ -1,6 +1,7 @@
|
||||
PaneContainer = require 'pane-container'
|
||||
Pane = require 'pane'
|
||||
{View, $$} = require 'space-pen'
|
||||
_ = require 'underscore'
|
||||
$ = require 'jquery'
|
||||
|
||||
describe "PaneContainer", ->
|
||||
@@ -9,12 +10,13 @@ describe "PaneContainer", ->
|
||||
beforeEach ->
|
||||
class TestView extends View
|
||||
registerDeserializer(this)
|
||||
@deserialize: ({myText}) -> new TestView(myText)
|
||||
@deserialize: ({name}) -> new TestView(name)
|
||||
@content: -> @div tabindex: -1
|
||||
initialize: (@myText) -> @text(@myText)
|
||||
serialize: -> deserializer: 'TestView', myText: @myText
|
||||
getPath: -> "/tmp/hi"
|
||||
initialize: (@name) -> @text(@name)
|
||||
serialize: -> { deserializer: 'TestView', @name }
|
||||
getUri: -> "/tmp/#{@name}"
|
||||
save: -> @saved = true
|
||||
isEqual: (other) -> @name is other.name
|
||||
|
||||
container = new PaneContainer
|
||||
pane1 = new Pane(new TestView('1'))
|
||||
@@ -74,6 +76,56 @@ describe "PaneContainer", ->
|
||||
pane4.splitDown()
|
||||
expect(panes).toEqual []
|
||||
|
||||
describe ".restoreItem()", ->
|
||||
describe "when there is an active pane", ->
|
||||
it "reconstructs and shows the last-closed pane item", ->
|
||||
expect(container.getActivePane()).toBe pane3
|
||||
item3 = pane3.activeItem
|
||||
item4 = new TestView('4')
|
||||
pane3.showItem(item4)
|
||||
|
||||
pane3.destroyItem(item3)
|
||||
pane3.destroyItem(item4)
|
||||
expect(container.getActivePane()).toBe pane1
|
||||
|
||||
expect(container.restoreItem()).toBeTruthy()
|
||||
expect(pane1.activeItem).toEqual item4
|
||||
|
||||
expect(container.restoreItem()).toBeTruthy()
|
||||
expect(pane1.activeItem).toEqual item3
|
||||
|
||||
expect(container.restoreItem()).toBeFalsy()
|
||||
expect(pane1.activeItem).toEqual item3
|
||||
|
||||
describe "when there is no active pane", ->
|
||||
it "attaches a new pane with the reconstructed last pane item", ->
|
||||
pane1.remove()
|
||||
pane2.remove()
|
||||
item3 = pane3.activeItem
|
||||
pane3.destroyItem(item3)
|
||||
expect(container.getActivePane()).toBeUndefined()
|
||||
|
||||
container.restoreItem()
|
||||
|
||||
expect(container.getActivePane().activeItem).toEqual item3
|
||||
|
||||
it "does not reopen an item that is already open", ->
|
||||
item3 = pane3.activeItem
|
||||
item4 = new TestView('4')
|
||||
pane3.showItem(item4)
|
||||
pane3.destroyItem(item3)
|
||||
pane3.destroyItem(item4)
|
||||
|
||||
expect(container.getActivePane()).toBe pane1
|
||||
pane1.showItem(new TestView('4'))
|
||||
|
||||
expect(container.restoreItem()).toBeTruthy()
|
||||
expect(_.pluck(pane1.getItems(), 'name')).toEqual ['1', '4', '3']
|
||||
expect(pane1.activeItem).toEqual item3
|
||||
|
||||
expect(container.restoreItem()).toBeFalsy()
|
||||
expect(pane1.activeItem).toEqual item3
|
||||
|
||||
describe ".saveAll()", ->
|
||||
it "saves all open pane items", ->
|
||||
pane1.showItem(new TestView('4'))
|
||||
|
||||
@@ -125,7 +125,7 @@ describe "Pane", ->
|
||||
expect(editSession2.destroyed).toBeFalsy()
|
||||
|
||||
describe "if the [Save] option is selected", ->
|
||||
describe "when the item has a path", ->
|
||||
describe "when the item has a uri", ->
|
||||
it "saves the item before removing and destroying it", ->
|
||||
atom.confirm.selectOption('Save')
|
||||
|
||||
@@ -133,8 +133,8 @@ describe "Pane", ->
|
||||
expect(pane.getItems().indexOf(editSession2)).toBe -1
|
||||
expect(editSession2.destroyed).toBeTruthy()
|
||||
|
||||
describe "when the item has no path", ->
|
||||
it "presents a save-as dialog, then saves the item with the given path before removing and destroying it", ->
|
||||
describe "when the item has no uri", ->
|
||||
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')
|
||||
@@ -286,7 +286,7 @@ describe "Pane", ->
|
||||
expect(pane.getItems()).toEqual [editSession1]
|
||||
|
||||
describe "core:save", ->
|
||||
describe "when the current item has a path", ->
|
||||
describe "when the current item has a uri", ->
|
||||
describe "when the current item has a save method", ->
|
||||
it "saves the current item", ->
|
||||
spyOn(editSession2, 'save')
|
||||
@@ -299,7 +299,7 @@ describe "Pane", ->
|
||||
expect(pane.activeItem.save).toBeUndefined()
|
||||
pane.trigger 'core:save'
|
||||
|
||||
describe "when the current item has no path", ->
|
||||
describe "when the current item has no uri", ->
|
||||
beforeEach ->
|
||||
spyOn(atom, 'showSaveDialog')
|
||||
|
||||
@@ -576,17 +576,17 @@ describe "Pane", ->
|
||||
expect(pane1.outerWidth()).toBe container.width()
|
||||
|
||||
describe "autosave", ->
|
||||
[initialActiveItem, initialActiveItemPath] = []
|
||||
[initialActiveItem, initialActiveItemUri] = []
|
||||
|
||||
beforeEach ->
|
||||
initialActiveItem = pane.activeItem
|
||||
initialActiveItemPath = null
|
||||
pane.activeItem.getPath = -> initialActiveItemPath
|
||||
initialActiveItemUri = null
|
||||
pane.activeItem.getUri = -> initialActiveItemUri
|
||||
pane.activeItem.save = jasmine.createSpy("activeItem.save")
|
||||
spyOn(pane, 'saveItem').andCallThrough()
|
||||
|
||||
describe "when the active view loses focus", ->
|
||||
it "saves the item if core.autosave is true and the item has a path", ->
|
||||
it "saves the item if core.autosave is true and the item has a uri", ->
|
||||
pane.activeView.trigger 'focusout'
|
||||
expect(pane.saveItem).not.toHaveBeenCalled()
|
||||
expect(pane.activeItem.save).not.toHaveBeenCalled()
|
||||
@@ -596,12 +596,12 @@ describe "Pane", ->
|
||||
expect(pane.saveItem).not.toHaveBeenCalled()
|
||||
expect(pane.activeItem.save).not.toHaveBeenCalled()
|
||||
|
||||
initialActiveItemPath = '/tmp/hi'
|
||||
initialActiveItemUri = '/tmp/hi'
|
||||
pane.activeView.trigger 'focusout'
|
||||
expect(pane.activeItem.save).toHaveBeenCalled()
|
||||
|
||||
describe "when an item becomes inactive", ->
|
||||
it "saves the item if core.autosave is true and the item has a path", ->
|
||||
it "saves the item if core.autosave is true and the item has a uri", ->
|
||||
expect(view2).not.toBe pane.activeItem
|
||||
expect(pane.saveItem).not.toHaveBeenCalled()
|
||||
expect(initialActiveItem.save).not.toHaveBeenCalled()
|
||||
@@ -614,12 +614,12 @@ describe "Pane", ->
|
||||
expect(initialActiveItem.save).not.toHaveBeenCalled()
|
||||
|
||||
pane.showItem(initialActiveItem)
|
||||
initialActiveItemPath = '/tmp/hi'
|
||||
initialActiveItemUri = '/tmp/hi'
|
||||
pane.showItem(view2)
|
||||
expect(initialActiveItem.save).toHaveBeenCalled()
|
||||
|
||||
describe "when an item is destroyed", ->
|
||||
it "saves the item if core.autosave is true and the item has a path", ->
|
||||
it "saves the item if core.autosave is true and the item has a uri", ->
|
||||
# doesn't have to be the active item
|
||||
expect(view2).not.toBe pane.activeItem
|
||||
pane.showItem(view2)
|
||||
@@ -628,19 +628,19 @@ describe "Pane", ->
|
||||
expect(pane.saveItem).not.toHaveBeenCalled()
|
||||
|
||||
config.set("core.autosave", true)
|
||||
view2.getPath = -> undefined
|
||||
view2.getUri = -> undefined
|
||||
view2.save = ->
|
||||
pane.destroyItem(view2)
|
||||
expect(pane.saveItem).not.toHaveBeenCalled()
|
||||
|
||||
initialActiveItemPath = '/tmp/hi'
|
||||
initialActiveItemUri = '/tmp/hi'
|
||||
pane.destroyItem(initialActiveItem)
|
||||
expect(initialActiveItem.save).toHaveBeenCalled()
|
||||
|
||||
describe ".itemForPath(path)", ->
|
||||
it "returns the item for which a call to .getPath() returns the given path", ->
|
||||
expect(pane.itemForPath(editSession1.getPath())).toBe editSession1
|
||||
expect(pane.itemForPath(editSession2.getPath())).toBe editSession2
|
||||
describe ".itemForUri(uri)", ->
|
||||
it "returns the item for which a call to .getUri() returns the given uri", ->
|
||||
expect(pane.itemForUri(editSession1.getUri())).toBe editSession1
|
||||
expect(pane.itemForUri(editSession2.getUri())).toBe editSession2
|
||||
|
||||
describe "serialization", ->
|
||||
it "can serialize and deserialize the pane and all its serializable items", ->
|
||||
|
||||
@@ -25,6 +25,12 @@ class EditSession
|
||||
session.setCursorScreenPosition(state.cursorScreenPosition)
|
||||
session
|
||||
|
||||
@identifiedBy: 'path'
|
||||
|
||||
@deserializesToSameObject: (state, editSession) ->
|
||||
state.path
|
||||
|
||||
|
||||
scrollTop: 0
|
||||
scrollLeft: 0
|
||||
languageMode: null
|
||||
@@ -151,6 +157,7 @@ class EditSession
|
||||
saveAs: (path) -> @buffer.saveAs(path)
|
||||
getFileExtension: -> @buffer.getExtension()
|
||||
getPath: -> @buffer.getPath()
|
||||
getUri: -> @getPath()
|
||||
isBufferRowBlank: (bufferRow) -> @buffer.isRowBlank(bufferRow)
|
||||
nextNonBlankBufferRow: (bufferRow) -> @buffer.nextNonBlankRow(bufferRow)
|
||||
getEofBufferPosition: -> @buffer.getEofPosition()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{View} = require 'space-pen'
|
||||
Pane = require 'pane'
|
||||
$ = require 'jquery'
|
||||
|
||||
module.exports =
|
||||
@@ -13,6 +14,9 @@ class PaneContainer extends View
|
||||
@content: ->
|
||||
@div id: 'panes'
|
||||
|
||||
initialize: ->
|
||||
@destroyedItemStates = []
|
||||
|
||||
serialize: ->
|
||||
deserializer: 'PaneContainer'
|
||||
root: @getRoot()?.serialize()
|
||||
@@ -33,6 +37,24 @@ class PaneContainer extends View
|
||||
nextIndex = (currentIndex + 1) % panes.length
|
||||
panes[nextIndex].makeActive()
|
||||
|
||||
restoreItem: ->
|
||||
if lastItemState = @destroyedItemStates.pop()
|
||||
if activePane = @getActivePane()
|
||||
activePane.showItem(deserialize(lastItemState))
|
||||
true
|
||||
else
|
||||
@append(new Pane(deserialize(lastItemState)))
|
||||
|
||||
itemDestroyed: (item) ->
|
||||
state = item.serialize?()
|
||||
state.uri ?= item.getUri?()
|
||||
@destroyedItemStates.push(state) if state?
|
||||
|
||||
itemAdded: (item) ->
|
||||
itemUri = item.getUri?()
|
||||
@destroyedItemStates = @destroyedItemStates.filter (itemState) ->
|
||||
itemState.uri isnt itemUri
|
||||
|
||||
getRoot: ->
|
||||
@children().first().view()
|
||||
|
||||
|
||||
@@ -111,6 +111,7 @@ class Pane extends View
|
||||
return if _.include(@items, item)
|
||||
index = @getActiveItemIndex() + 1
|
||||
@items.splice(index, 0, item)
|
||||
@getContainer().itemAdded(item)
|
||||
@trigger 'pane:item-added', [item, index]
|
||||
item
|
||||
|
||||
@@ -119,8 +120,10 @@ class Pane extends View
|
||||
false
|
||||
|
||||
destroyItem: (item) ->
|
||||
container = @getContainer()
|
||||
reallyDestroyItem = =>
|
||||
@removeItem(item)
|
||||
container.itemDestroyed(item)
|
||||
item.destroy?()
|
||||
|
||||
@autosaveItem(item)
|
||||
@@ -137,7 +140,7 @@ class Pane extends View
|
||||
@destroyItem(item) for item in @getItems() when item isnt @activeItem
|
||||
|
||||
promptToSaveItem: (item, nextAction) ->
|
||||
path = item.getPath()
|
||||
uri = item.getUri()
|
||||
atom.confirm(
|
||||
"'#{item.getTitle()}' has changes, do you want to save them?"
|
||||
"Your changes will be lost if close this item without saving."
|
||||
@@ -153,7 +156,7 @@ class Pane extends View
|
||||
@saveItemAs(@activeItem)
|
||||
|
||||
saveItem: (item, nextAction) ->
|
||||
if item.getPath?()
|
||||
if item.getUri?()
|
||||
item.save()
|
||||
nextAction?()
|
||||
else
|
||||
@@ -173,7 +176,7 @@ class Pane extends View
|
||||
@autosaveItem(@activeItem)
|
||||
|
||||
autosaveItem: (item) ->
|
||||
@saveItem(item) if config.get('core.autosave') and item.getPath?()
|
||||
@saveItem(item) if config.get('core.autosave') and item.getUri?()
|
||||
|
||||
removeItem: (item) ->
|
||||
index = @items.indexOf(item)
|
||||
@@ -194,8 +197,8 @@ class Pane extends View
|
||||
@removeItem(item)
|
||||
pane.addItem(item, index)
|
||||
|
||||
itemForPath: (path) ->
|
||||
_.detect @items, (item) -> item.getPath?() is path
|
||||
itemForUri: (uri) ->
|
||||
_.detect @items, (item) -> item.getUri?() is uri
|
||||
|
||||
cleanupItemView: (item) ->
|
||||
if item instanceof $
|
||||
|
||||
@@ -92,7 +92,7 @@ class RootView extends View
|
||||
changeFocus = options.changeFocus ? true
|
||||
path = project.resolve(path) if path?
|
||||
if activePane = @getActivePane()
|
||||
if editSession = activePane.itemForPath(path)
|
||||
if editSession = activePane.itemForUri(path)
|
||||
activePane.showItem(editSession)
|
||||
else
|
||||
editSession = project.buildEditSession(path)
|
||||
|
||||
@@ -155,7 +155,10 @@ window.unregisterDeserializer = (klass) ->
|
||||
delete deserializers[klass.name]
|
||||
|
||||
window.deserialize = (state) ->
|
||||
deserializers[state?.deserializer]?.deserialize(state)
|
||||
getDeserializer(state)?.deserialize(state)
|
||||
|
||||
window.getDeserializer = (state) ->
|
||||
deserializers[state?.deserializer]
|
||||
|
||||
window.measure = (description, fn) ->
|
||||
start = new Date().getTime()
|
||||
|
||||
Reference in New Issue
Block a user