Pass AppDelegate to Workspace, Pane instead of bound functions

Signed-off-by: Max Brunsfeld <maxbrunsfeld@github.com>
This commit is contained in:
Nathan Sobo 2015-10-13 18:54:48 -06:00 committed by Max Brunsfeld
parent 20e07649d4
commit 84aa8471b4
11 changed files with 50 additions and 64 deletions

View File

@ -213,9 +213,7 @@ describe "AtomEnvironment", ->
describe "::unloadEditorWindow()", -> describe "::unloadEditorWindow()", ->
it "saves the serialized state of the window so it can be deserialized after reload", -> it "saves the serialized state of the window so it can be deserialized after reload", ->
atomEnvironment = new AtomEnvironment(applicationDelegate: { atomEnvironment = new AtomEnvironment(applicationDelegate: atom.applicationDelegate)
isWindowFullScreen: -> false
})
spyOn(atomEnvironment, 'saveStateSync') spyOn(atomEnvironment, 'saveStateSync')
workspaceState = atomEnvironment.workspace.serialize() workspaceState = atomEnvironment.workspace.serialize()
@ -233,9 +231,7 @@ describe "AtomEnvironment", ->
describe "::destroy()", -> describe "::destroy()", ->
it "unsubscribes from all buffers", -> it "unsubscribes from all buffers", ->
atomEnvironment = new AtomEnvironment(applicationDelegate: { atomEnvironment = new AtomEnvironment(applicationDelegate: atom.applicationDelegate)
isWindowFullScreen: -> false
})
waitsForPromise -> waitsForPromise ->
atomEnvironment.workspace.open("sample.js") atomEnvironment.workspace.open("sample.js")

View File

@ -16,7 +16,7 @@ module.exports = ({logFile, headless, testPaths, buildAtomEnvironment}) ->
ApplicationDelegate = require '../src/application-delegate' ApplicationDelegate = require '../src/application-delegate'
applicationDelegate = new ApplicationDelegate() applicationDelegate = new ApplicationDelegate()
applicationDelegate.setWindowRepresentedFilename = -> applicationDelegate.setRepresentedFilename = ->
applicationDelegate.setWindowDocumentEdited = -> applicationDelegate.setWindowDocumentEdited = ->
window.atom = buildAtomEnvironment({applicationDelegate}) window.atom = buildAtomEnvironment({applicationDelegate})

View File

@ -5,11 +5,11 @@ describe "PaneContainer", ->
[confirm, params] = [] [confirm, params] = []
beforeEach -> beforeEach ->
confirm = jasmine.createSpy('confirm').andReturn(0) confirm = spyOn(atom.applicationDelegate, 'confirm').andReturn(0)
params = { params = {
config: atom.config, config: atom.config,
confirm: confirm,
deserializerManager: atom.deserializers deserializerManager: atom.deserializers
applicationDelegate: atom.applicationDelegate
} }
describe "serialization", -> describe "serialization", ->

View File

@ -5,7 +5,7 @@ PaneAxis = require '../src/pane-axis'
PaneContainer = require '../src/pane-container' PaneContainer = require '../src/pane-container'
describe "Pane", -> describe "Pane", ->
[confirm, deserializerDisposable] = [] [confirm, showSaveDialog, deserializerDisposable] = []
class Item class Item
@deserialize: ({name, uri}) -> new this(name, uri) @deserialize: ({name, uri}) -> new this(name, uri)
@ -20,7 +20,8 @@ describe "Pane", ->
isDestroyed: -> @destroyed isDestroyed: -> @destroyed
beforeEach -> beforeEach ->
confirm = jasmine.createSpy('confirm') confirm = spyOn(atom.applicationDelegate, 'confirm')
showSaveDialog = spyOn(atom.applicationDelegate, 'showSaveDialog')
deserializerDisposable = atom.deserializers.add(Item) deserializerDisposable = atom.deserializers.add(Item)
afterEach -> afterEach ->
@ -28,7 +29,7 @@ describe "Pane", ->
paneParams = (params) -> paneParams = (params) ->
extend({ extend({
confirm: confirm, applicationDelegate: atom.applicationDelegate,
config: atom.config, config: atom.config,
deserializerManager: atom.deserializers, deserializerManager: atom.deserializers,
notificationManager: atom.notifications notificationManager: atom.notifications
@ -48,7 +49,7 @@ describe "Pane", ->
[container, pane1, pane2] = [] [container, pane1, pane2] = []
beforeEach -> beforeEach ->
container = new PaneContainer(config: atom.config, confirm: confirm) container = new PaneContainer(config: atom.config, applicationDelegate: atom.applicationDelegate)
container.getActivePane().splitRight() container.getActivePane().splitRight()
[pane1, pane2] = container.getPanes() [pane1, pane2] = container.getPanes()
@ -117,7 +118,7 @@ describe "Pane", ->
it "throws an exception if the item is already present on a pane", -> it "throws an exception if the item is already present on a pane", ->
item = new Item("A") item = new Item("A")
container = new PaneContainer(config: atom.config, confirm: confirm) container = new PaneContainer(config: atom.config, applicationDelegate: atom.applicationDelegate)
pane1 = container.getActivePane() pane1 = container.getActivePane()
pane1.addItem(item) pane1.addItem(item)
pane2 = pane1.splitRight() pane2 = pane1.splitRight()
@ -281,11 +282,11 @@ describe "Pane", ->
it "presents a save-as dialog, then saves the item with the given uri before removing and destroying it", -> it "presents a save-as dialog, then saves the item with the given uri before removing and destroying it", ->
itemURI = null itemURI = null
spyOn(atom, 'showSaveDialogSync').andReturn("/selected/path") showSaveDialog.andReturn("/selected/path")
confirm.andReturn(0) confirm.andReturn(0)
pane.destroyItem(item1) pane.destroyItem(item1)
expect(atom.showSaveDialogSync).toHaveBeenCalled() expect(showSaveDialog).toHaveBeenCalled()
expect(item1.saveAs).toHaveBeenCalledWith("/selected/path") expect(item1.saveAs).toHaveBeenCalledWith("/selected/path")
expect(item1 in pane.getItems()).toBe false expect(item1 in pane.getItems()).toBe false
expect(item1.isDestroyed()).toBe true expect(item1.isDestroyed()).toBe true
@ -379,7 +380,7 @@ describe "Pane", ->
beforeEach -> beforeEach ->
pane = new Pane(paneParams(items: [new Item("A")])) pane = new Pane(paneParams(items: [new Item("A")]))
spyOn(atom, 'showSaveDialogSync').andReturn('/selected/path') showSaveDialog.andReturn('/selected/path')
describe "when the active item has a uri", -> describe "when the active item has a uri", ->
beforeEach -> beforeEach ->
@ -401,14 +402,14 @@ describe "Pane", ->
it "opens a save dialog and saves the current item as the selected path", -> it "opens a save dialog and saves the current item as the selected path", ->
pane.getActiveItem().saveAs = jasmine.createSpy("saveAs") pane.getActiveItem().saveAs = jasmine.createSpy("saveAs")
pane.saveActiveItem() pane.saveActiveItem()
expect(atom.showSaveDialogSync).toHaveBeenCalled() expect(showSaveDialog).toHaveBeenCalled()
expect(pane.getActiveItem().saveAs).toHaveBeenCalledWith('/selected/path') expect(pane.getActiveItem().saveAs).toHaveBeenCalledWith('/selected/path')
describe "when the current item has no saveAs method", -> describe "when the current item has no saveAs method", ->
it "does nothing", -> it "does nothing", ->
expect(pane.getActiveItem().saveAs).toBeUndefined() expect(pane.getActiveItem().saveAs).toBeUndefined()
pane.saveActiveItem() pane.saveActiveItem()
expect(atom.showSaveDialogSync).not.toHaveBeenCalled() expect(showSaveDialog).not.toHaveBeenCalled()
describe "when the item's saveAs method throws a well-known IO error", -> describe "when the item's saveAs method throws a well-known IO error", ->
notificationSpy = null notificationSpy = null
@ -434,21 +435,21 @@ describe "Pane", ->
beforeEach -> beforeEach ->
pane = new Pane(paneParams(items: [new Item("A")])) pane = new Pane(paneParams(items: [new Item("A")]))
spyOn(atom, 'showSaveDialogSync').andReturn('/selected/path') showSaveDialog.andReturn('/selected/path')
describe "when the current item has a saveAs method", -> describe "when the current item has a saveAs method", ->
it "opens the save dialog and calls saveAs on the item with the selected path", -> it "opens the save dialog and calls saveAs on the item with the selected path", ->
pane.getActiveItem().path = __filename pane.getActiveItem().path = __filename
pane.getActiveItem().saveAs = jasmine.createSpy("saveAs") pane.getActiveItem().saveAs = jasmine.createSpy("saveAs")
pane.saveActiveItemAs() pane.saveActiveItemAs()
expect(atom.showSaveDialogSync).toHaveBeenCalledWith(defaultPath: __filename) expect(showSaveDialog).toHaveBeenCalledWith(defaultPath: __filename)
expect(pane.getActiveItem().saveAs).toHaveBeenCalledWith('/selected/path') expect(pane.getActiveItem().saveAs).toHaveBeenCalledWith('/selected/path')
describe "when the current item does not have a saveAs method", -> describe "when the current item does not have a saveAs method", ->
it "does nothing", -> it "does nothing", ->
expect(pane.getActiveItem().saveAs).toBeUndefined() expect(pane.getActiveItem().saveAs).toBeUndefined()
pane.saveActiveItemAs() pane.saveActiveItemAs()
expect(atom.showSaveDialogSync).not.toHaveBeenCalled() expect(showSaveDialog).not.toHaveBeenCalled()
describe "when the item's saveAs method throws a well-known IO error", -> describe "when the item's saveAs method throws a well-known IO error", ->
notificationSpy = null notificationSpy = null

View File

@ -0,0 +1 @@
undefined

1
spec/sample.js Normal file
View File

@ -0,0 +1 @@
undefined

View File

@ -14,8 +14,8 @@ describe "Workspace", ->
beforeEach -> beforeEach ->
workspace = atom.workspace workspace = atom.workspace
workspace.resetFontSize() workspace.resetFontSize()
spyOn(workspace, "confirm") spyOn(atom.applicationDelegate, "confirm")
setDocumentEdited = spyOn(workspace, 'setDocumentEdited') setDocumentEdited = spyOn(atom.applicationDelegate, 'setWindowDocumentEdited')
atom.project.setPaths([atom.project.getDirectories()[0]?.resolve('dir')]) atom.project.setPaths([atom.project.getDirectories()[0]?.resolve('dir')])
waits(1) waits(1)
@ -31,10 +31,8 @@ describe "Workspace", ->
config: atom.config, project: atom.project, packageManager: atom.packages, config: atom.config, project: atom.project, packageManager: atom.packages,
grammarRegistry: atom.grammars, deserializerManager: atom.deserializers, grammarRegistry: atom.grammars, deserializerManager: atom.deserializers,
notificationManager: atom.notifications, clipboard: atom.clipboard, notificationManager: atom.notifications, clipboard: atom.clipboard,
setRepresentedFilename: atom.setRepresentedFilename.bind(atom), applicationDelegate: atom.applicationDelegate,
setDocumentEdited: atom.setDocumentEdited.bind(atom),
viewRegistry: atom.views, assert: atom.assert.bind(atom), viewRegistry: atom.views, assert: atom.assert.bind(atom),
confirm: atom.confirm.bind(atom)
}) })
atom.workspace.deserialize(workspaceState, atom.deserializers) atom.workspace.deserialize(workspaceState, atom.deserializers)
@ -347,8 +345,8 @@ describe "Workspace", ->
describe "when the file is over 20MB", -> describe "when the file is over 20MB", ->
it "prompts the user to make sure they want to open a file this big", -> it "prompts the user to make sure they want to open a file this big", ->
spyOn(fs, 'getSizeSync').andReturn 20 * 1048577 # 20MB spyOn(fs, 'getSizeSync').andReturn 20 * 1048577 # 20MB
workspace.confirm.andCallFake -> selectedButtonIndex atom.applicationDelegate.confirm.andCallFake -> selectedButtonIndex
atom.workspace.confirm() atom.applicationDelegate.confirm()
selectedButtonIndex = 1 # cancel selectedButtonIndex = 1 # cancel
editor = null editor = null
@ -357,16 +355,16 @@ describe "Workspace", ->
runs -> runs ->
expect(editor).toBeUndefined() expect(editor).toBeUndefined()
expect(workspace.confirm).toHaveBeenCalled() expect(atom.applicationDelegate.confirm).toHaveBeenCalled()
workspace.confirm.reset() atom.applicationDelegate.confirm.reset()
selectedButtonIndex = 0 # open the file selectedButtonIndex = 0 # open the file
waitsForPromise -> waitsForPromise ->
workspace.open('sample.js').then (e) -> editor = e workspace.open('sample.js').then (e) -> editor = e
runs -> runs ->
expect(workspace.confirm).toHaveBeenCalled() expect(atom.applicationDelegate.confirm).toHaveBeenCalled()
expect(editor.displayBuffer.largeFileMode).toBe true expect(editor.displayBuffer.largeFileMode).toBe true
describe "when passed a path that matches a custom opener", -> describe "when passed a path that matches a custom opener", ->
@ -633,9 +631,7 @@ describe "Workspace", ->
config: atom.config, project: atom.project, packageManager: atom.packages, config: atom.config, project: atom.project, packageManager: atom.packages,
notificationManager: atom.notifications, deserializerManager: atom.deserializers, notificationManager: atom.notifications, deserializerManager: atom.deserializers,
clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars, clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars,
setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), applicationDelegate: atom.applicationDelegate, assert: atom.assert.bind(atom)
setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion(),
assert: atom.assert.bind(atom)
}) })
workspace2.deserialize(state, atom.deserializers) workspace2.deserialize(state, atom.deserializers)
expect(jsPackage.loadGrammarsSync.callCount).toBe 1 expect(jsPackage.loadGrammarsSync.callCount).toBe 1
@ -693,9 +689,7 @@ describe "Workspace", ->
config: atom.config, project: atom.project, packageManager: atom.packages, config: atom.config, project: atom.project, packageManager: atom.packages,
notificationManager: atom.notifications, deserializerManager: atom.deserializers, notificationManager: atom.notifications, deserializerManager: atom.deserializers,
clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars, clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars,
setRepresentedFilename: jasmine.createSpy('setRepresentedFilename'), applicationDelegate: atom.applicationDelegate, assert: atom.assert.bind(atom)
setDocumentEdited: setDocumentEdited, atomVersion: atom.getVersion(),
assert: atom.assert.bind(atom)
}) })
workspace2.deserialize(atom.workspace.serialize(), atom.deserializers) workspace2.deserialize(atom.workspace.serialize(), atom.deserializers)
item = atom.workspace.getActivePaneItem() item = atom.workspace.getActivePaneItem()

View File

@ -175,8 +175,7 @@ class AtomEnvironment extends Model
@workspace = new Workspace({ @workspace = new Workspace({
@config, @project, packageManager: @packages, grammarRegistry: @grammars, deserializerManager: @deserializers, @config, @project, packageManager: @packages, grammarRegistry: @grammars, deserializerManager: @deserializers,
notificationManager: @notifications, setRepresentedFilename: @setRepresentedFilename.bind(this), notificationManager: @notifications, @applicationDelegate, @clipboard, viewRegistry: @views, assert: @assert.bind(this)
setDocumentEdited: @setDocumentEdited.bind(this), @clipboard, viewRegistry: @views, assert: @assert.bind(this), confirm: @confirm.bind(this)
}) })
@themes.workspace = @workspace @themes.workspace = @workspace

View File

@ -15,12 +15,12 @@ class PaneContainer extends Model
constructor: (params) -> constructor: (params) ->
super super
{@config, notificationManager, deserializerManager, confirm} = params {@config, applicationDelegate, notificationManager, deserializerManager} = params
@emitter = new Emitter @emitter = new Emitter
@subscriptions = new CompositeDisposable @subscriptions = new CompositeDisposable
@itemRegistry = new ItemRegistry @itemRegistry = new ItemRegistry
@setRoot(new Pane({container: this, @config, notificationManager, deserializerManager, confirm})) @setRoot(new Pane({container: this, @config, applicationDelegate, notificationManager, deserializerManager}))
@setActivePane(@getRoot()) @setActivePane(@getRoot())
@monitorActivePaneItem() @monitorActivePaneItem()
@monitorPaneItems() @monitorPaneItems()

View File

@ -14,9 +14,7 @@ class Pane extends Model
activeItem: undefined activeItem: undefined
focused: false focused: false
@deserialize: (state, atomEnvironment) -> @deserialize: (state, {deserializers, applicationDelegate, config, notifications}) ->
{deserializers, config, notifications} = atomEnvironment
confirm = atomEnvironment.confirm.bind(atomEnvironment)
{items, activeItemURI, activeItemUri} = state {items, activeItemURI, activeItemUri} = state
activeItemURI ?= activeItemUri activeItemURI ?= activeItemUri
state.items = compact(items.map (itemState) -> deserializers.deserialize(itemState)) state.items = compact(items.map (itemState) -> deserializers.deserialize(itemState))
@ -27,15 +25,14 @@ class Pane extends Model
new Pane(extend(state, { new Pane(extend(state, {
deserializerManager: deserializers, deserializerManager: deserializers,
notificationManager: notifications, notificationManager: notifications,
confirm: confirm, config, applicationDelegate
config: config
})) }))
constructor: (params) -> constructor: (params) ->
super super
{ {
@activeItem, @focused, @confirm, @notificationManager, @config, @activeItem, @focused, @applicationDelegate, @notificationManager, @config,
@deserializerManager @deserializerManager
} = params } = params
@ -465,7 +462,7 @@ class Pane extends Model
else else
return true return true
chosen = @confirm chosen = @applicationDelegate.confirm
message: "'#{item.getTitle?() ? uri}' has changes, do you want to save them?" message: "'#{item.getTitle?() ? uri}' has changes, do you want to save them?"
detailedMessage: "Your changes will be lost if you close this item without saving." detailedMessage: "Your changes will be lost if you close this item without saving."
buttons: ["Save", "Cancel", "Don't Save"] buttons: ["Save", "Cancel", "Don't Save"]
@ -518,7 +515,7 @@ class Pane extends Model
saveOptions = item.getSaveDialogOptions?() ? {} saveOptions = item.getSaveDialogOptions?() ? {}
saveOptions.defaultPath ?= item.getPath() saveOptions.defaultPath ?= item.getPath()
newItemPath = atom.showSaveDialogSync(saveOptions) newItemPath = @applicationDelegate.showSaveDialog(saveOptions)
if newItemPath if newItemPath
try try
item.saveAs(newItemPath) item.saveAs(newItemPath)
@ -650,7 +647,7 @@ class Pane extends Model
@parent.replaceChild(this, new PaneAxis({@container, orientation, children: [this], @flexScale})) @parent.replaceChild(this, new PaneAxis({@container, orientation, children: [this], @flexScale}))
@setFlexScale(1) @setFlexScale(1)
newPane = new Pane(extend({@confirm, @deserializerManager, @config}, params)) newPane = new Pane(extend({@applicationDelegate, @deserializerManager, @config}, params))
switch side switch side
when 'before' then @parent.insertChildBefore(this, newPane) when 'before' then @parent.insertChildBefore(this, newPane)
when 'after' then @parent.insertChildAfter(this, newPane) when 'after' then @parent.insertChildAfter(this, newPane)

View File

@ -28,15 +28,15 @@ class Workspace extends Model
{ {
@packageManager, @config, @project, @grammarRegistry, @notificationManager, @packageManager, @config, @project, @grammarRegistry, @notificationManager,
@clipboard, @viewRegistry, @grammarRegistry, @setRepresentedFilename, @clipboard, @viewRegistry, @grammarRegistry, @applicationDelegate, @assert,
@setDocumentEdited, @assert, @confirm, @deserializerManager @deserializerManager
} = params } = params
@emitter = new Emitter @emitter = new Emitter
@openers = [] @openers = []
@destroyedItemURIs = [] @destroyedItemURIs = []
@paneContainer = new PaneContainer({@config, @confirm, @notificationManager, @deserializerManager}) @paneContainer = new PaneContainer({@config, @applicationDelegate, @notificationManager, @deserializerManager})
@paneContainer.onDidDestroyPaneItem(@didDestroyPaneItem) @paneContainer.onDidDestroyPaneItem(@didDestroyPaneItem)
@defaultDirectorySearcher = new DefaultDirectorySearcher() @defaultDirectorySearcher = new DefaultDirectorySearcher()
@ -58,7 +58,7 @@ class Workspace extends Model
@paneContainer.destroy() @paneContainer.destroy()
panelContainer.destroy() for panelContainer in @panelContainers panelContainer.destroy() for panelContainer in @panelContainers
@paneContainer = new PaneContainer({@config, @confirm, @notificationManager, @deserializerManager}) @paneContainer = new PaneContainer({@config, @applicationDelegate, @notificationManager, @deserializerManager})
@paneContainer.onDidDestroyPaneItem(@didDestroyPaneItem) @paneContainer.onDidDestroyPaneItem(@didDestroyPaneItem)
@panelContainers = @panelContainers =
@ -163,19 +163,19 @@ class Workspace extends Model
if item? and projectPath? if item? and projectPath?
document.title = "#{itemTitle} - #{projectPath} - #{appName}" document.title = "#{itemTitle} - #{projectPath} - #{appName}"
@setRepresentedFilename(itemPath ? projectPath) @applicationDelegate.setRepresentedFilename(itemPath ? projectPath)
else if projectPath? else if projectPath?
document.title = "#{projectPath} - #{appName}" document.title = "#{projectPath} - #{appName}"
@setRepresentedFilename(projectPath) @applicationDelegate.setRepresentedFilename(projectPath)
else else
document.title = "#{itemTitle} - #{appName}" document.title = "#{itemTitle} - #{appName}"
@setRepresentedFilename("") @applicationDelegate.setRepresentedFilename("")
# On OS X, fades the application window's proxy icon when the current file # On OS X, fades the application window's proxy icon when the current file
# has been modified. # has been modified.
updateDocumentEdited: => updateDocumentEdited: =>
modified = @getActivePaneItem()?.isModified?() ? false modified = @getActivePaneItem()?.isModified?() ? false
@setDocumentEdited(modified) @applicationDelegate.setWindowDocumentEdited(modified)
### ###
Section: Event Subscription Section: Event Subscription
@ -470,9 +470,6 @@ class Workspace extends Model
Promise.resolve(item) Promise.resolve(item)
.then (item) => .then (item) =>
if not pane
pane = new Pane({items: [item], @config, @confirm})
@paneContainer.root = pane
@itemOpened(item) @itemOpened(item)
pane.activateItem(item) if activateItem pane.activateItem(item) if activateItem
pane.activate() if activatePane pane.activate() if activatePane
@ -503,7 +500,7 @@ class Workspace extends Model
largeFileMode = fileSize >= 2 * 1048576 # 2MB largeFileMode = fileSize >= 2 * 1048576 # 2MB
if fileSize >= 20 * 1048576 # 20MB if fileSize >= 20 * 1048576 # 20MB
choice = @confirm choice = @applicationDelegate.confirm
message: 'Atom will be unresponsive during the loading of very large files.' message: 'Atom will be unresponsive during the loading of very large files.'
detailedMessage: "Do you still want to load this file?" detailedMessage: "Do you still want to load this file?"
buttons: ["Proceed", "Cancel"] buttons: ["Proceed", "Cancel"]
@ -521,7 +518,7 @@ class Workspace extends Model
buildTextEditor: (params) -> buildTextEditor: (params) ->
params = _.extend({ params = _.extend({
@config, @notificationManager, @packageManager, @clipboard, @viewRegistry, @config, @notificationManager, @packageManager, @clipboard, @viewRegistry,
@grammarRegistry, @project, @assert @grammarRegistry, @project, @assert, @applicationDelegate
}, params) }, params)
new TextEditor(params) new TextEditor(params)