diff --git a/benchmark/benchmark-bootstrap.coffee b/benchmark/benchmark-bootstrap.coffee
index 18d030e62..5d74df7de 100644
--- a/benchmark/benchmark-bootstrap.coffee
+++ b/benchmark/benchmark-bootstrap.coffee
@@ -1,4 +1,5 @@
-require '../src/atom'
+Atom = require '../src/atom'
+window.atom = new Atom()
{runSpecSuite} = require '../spec/jasmine-helper'
atom.openDevTools()
diff --git a/spec/atom-spec.coffee b/spec/atom-spec.coffee
index a5643443e..26ceea45c 100644
--- a/spec/atom-spec.coffee
+++ b/spec/atom-spec.coffee
@@ -6,29 +6,6 @@ describe "the `atom` global", ->
beforeEach ->
window.rootView = new RootView
- describe "base stylesheet loading", ->
- beforeEach ->
- rootView.append $$ -> @div class: 'editor'
- rootView.attachToDom()
- atom.themes.load()
- atom.watchThemes()
-
- afterEach ->
- atom.themes.unload()
- config.set('core.themes', [])
- atom.reloadBaseStylesheets()
-
- it "loads the correct values from the theme's ui-variables file", ->
- config.set('core.themes', ['theme-with-ui-variables'])
-
- # an override loaded in the base css
- expect(rootView.css("background-color")).toBe "rgb(0, 0, 255)"
-
- # from within the theme itself
- expect($(".editor").css("padding-top")).toBe "150px"
- expect($(".editor").css("padding-right")).toBe "150px"
- expect($(".editor").css("padding-bottom")).toBe "150px"
-
describe "package lifecycle methods", ->
describe ".loadPackage(name)", ->
describe "when the package has deferred deserializers", ->
@@ -205,15 +182,15 @@ describe "the `atom` global", ->
one = require.resolve("./fixtures/packages/package-with-stylesheets-manifest/stylesheets/1.css")
two = require.resolve("./fixtures/packages/package-with-stylesheets-manifest/stylesheets/2.less")
three = require.resolve("./fixtures/packages/package-with-stylesheets-manifest/stylesheets/3.css")
- expect(stylesheetElementForId(one)).not.toExist()
- expect(stylesheetElementForId(two)).not.toExist()
- expect(stylesheetElementForId(three)).not.toExist()
+ expect(atom.themes.stylesheetElementForId(one)).not.toExist()
+ expect(atom.themes.stylesheetElementForId(two)).not.toExist()
+ expect(atom.themes.stylesheetElementForId(three)).not.toExist()
atom.activatePackage("package-with-stylesheets-manifest")
- expect(stylesheetElementForId(one)).toExist()
- expect(stylesheetElementForId(two)).toExist()
- expect(stylesheetElementForId(three)).not.toExist()
+ expect(atom.themes.stylesheetElementForId(one)).toExist()
+ expect(atom.themes.stylesheetElementForId(two)).toExist()
+ expect(atom.themes.stylesheetElementForId(three)).not.toExist()
expect($('#jasmine-content').css('font-size')).toBe '1px'
describe "when the metadata does not contain a 'stylesheets' manifest", ->
@@ -221,14 +198,14 @@ describe "the `atom` global", ->
one = require.resolve("./fixtures/packages/package-with-stylesheets/stylesheets/1.css")
two = require.resolve("./fixtures/packages/package-with-stylesheets/stylesheets/2.less")
three = require.resolve("./fixtures/packages/package-with-stylesheets/stylesheets/3.css")
- expect(stylesheetElementForId(one)).not.toExist()
- expect(stylesheetElementForId(two)).not.toExist()
- expect(stylesheetElementForId(three)).not.toExist()
+ expect(atom.themes.stylesheetElementForId(one)).not.toExist()
+ expect(atom.themes.stylesheetElementForId(two)).not.toExist()
+ expect(atom.themes.stylesheetElementForId(three)).not.toExist()
atom.activatePackage("package-with-stylesheets")
- expect(stylesheetElementForId(one)).toExist()
- expect(stylesheetElementForId(two)).toExist()
- expect(stylesheetElementForId(three)).toExist()
+ expect(atom.themes.stylesheetElementForId(one)).toExist()
+ expect(atom.themes.stylesheetElementForId(two)).toExist()
+ expect(atom.themes.stylesheetElementForId(three)).toExist()
expect($('#jasmine-content').css('font-size')).toBe '3px'
describe "grammar loading", ->
@@ -298,8 +275,8 @@ describe "the `atom` global", ->
atom.activatePackage('package-with-serialize-error', immediate: true)
atom.activatePackage('package-with-serialization', immediate: true)
atom.deactivatePackages()
- expect(atom.packageStates['package-with-serialize-error']).toBeUndefined()
- expect(atom.packageStates['package-with-serialization']).toEqual someNumber: 1
+ expect(atom.packages.packageStates['package-with-serialize-error']).toBeUndefined()
+ expect(atom.packages.packageStates['package-with-serialization']).toEqual someNumber: 1
expect(console.error).toHaveBeenCalled()
it "removes the package's grammars", ->
@@ -320,9 +297,9 @@ describe "the `atom` global", ->
one = require.resolve("./fixtures/packages/package-with-stylesheets-manifest/stylesheets/1.css")
two = require.resolve("./fixtures/packages/package-with-stylesheets-manifest/stylesheets/2.less")
three = require.resolve("./fixtures/packages/package-with-stylesheets-manifest/stylesheets/3.css")
- expect(stylesheetElementForId(one)).not.toExist()
- expect(stylesheetElementForId(two)).not.toExist()
- expect(stylesheetElementForId(three)).not.toExist()
+ expect(atom.themes.stylesheetElementForId(one)).not.toExist()
+ expect(atom.themes.stylesheetElementForId(two)).not.toExist()
+ expect(atom.themes.stylesheetElementForId(three)).not.toExist()
it "removes the package's scoped-properties", ->
atom.activatePackage("package-with-scoped-properties")
diff --git a/spec/deserializer-manager-spec.coffee b/spec/deserializer-manager-spec.coffee
new file mode 100644
index 000000000..84bc4b9d0
--- /dev/null
+++ b/spec/deserializer-manager-spec.coffee
@@ -0,0 +1,33 @@
+DeserializerManager = require '../src/deserializer-manager'
+
+describe ".deserialize(state)", ->
+ deserializer = null
+
+ class Foo
+ @deserialize: ({name}) -> new Foo(name)
+ constructor: (@name) ->
+
+ beforeEach ->
+ deserializer = new DeserializerManager()
+ deserializer.registerDeserializer(Foo)
+
+ it "calls deserialize on the deserializer for the given state object, or returns undefined if one can't be found", ->
+ spyOn(console, 'warn')
+ object = deserializer.deserialize({ deserializer: 'Foo', name: 'Bar' })
+ expect(object.name).toBe 'Bar'
+ expect(deserializer.deserialize({ deserializer: 'Bogus' })).toBeUndefined()
+
+ describe "when the deserializer has a version", ->
+ beforeEach ->
+ Foo.version = 2
+
+ describe "when the deserialized state has a matching version", ->
+ it "attempts to deserialize the state", ->
+ object = deserializer.deserialize({ deserializer: 'Foo', version: 2, name: 'Bar' })
+ expect(object.name).toBe 'Bar'
+
+ describe "when the deserialized state has a non-matching version", ->
+ it "returns undefined", ->
+ expect(deserializer.deserialize({ deserializer: 'Foo', version: 3, name: 'Bar' })).toBeUndefined()
+ expect(deserializer.deserialize({ deserializer: 'Foo', version: 1, name: 'Bar' })).toBeUndefined()
+ expect(deserializer.deserialize({ deserializer: 'Foo', name: 'Bar' })).toBeUndefined()
diff --git a/spec/spec-bootstrap.coffee b/spec/spec-bootstrap.coffee
index 97a4d8471..d4df9c3cd 100644
--- a/spec/spec-bootstrap.coffee
+++ b/spec/spec-bootstrap.coffee
@@ -1,7 +1,8 @@
try
- require '../src/atom'
require '../src/window'
- atom.show()
+ Atom = require '../src/atom'
+ window.atom = new Atom()
+ window.atom.show()
{runSpecSuite} = require './jasmine-helper'
document.title = "Spec Suite"
diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee
index 74155a915..38db81e8c 100644
--- a/spec/spec-helper.coffee
+++ b/spec/spec-helper.coffee
@@ -14,12 +14,11 @@ TokenizedBuffer = require '../src/tokenized-buffer'
pathwatcher = require 'pathwatcher'
clipboard = require 'clipboard'
-atom.loadBaseStylesheets()
-requireStylesheet '../static/jasmine'
+atom.themes.loadBaseStylesheets()
+atom.themes.requireStylesheet '../static/jasmine'
fixturePackagesPath = path.resolve(__dirname, './fixtures/packages')
-config.packageDirPaths.unshift(fixturePackagesPath)
-keymap.loadBundledKeymaps()
+atom.keymap.loadBundledKeymaps()
[bindingSetsToRestore, bindingSetsByFirstKeystrokeToRestore] = []
$(window).on 'core:close', -> window.close()
@@ -36,20 +35,22 @@ specProjectPath = path.join(specDirectory, 'fixtures')
beforeEach ->
$.fx.off = true
- window.project = new Project(specProjectPath)
+ atom.project = new Project(specProjectPath)
+ window.project = atom.project
window.resetTimeouts()
- atom.packageStates = {}
+ atom.packages.packageStates = {}
spyOn(atom, 'saveWindowState')
- syntax.clearGrammarOverrides()
- syntax.clearProperties()
+ atom.syntax.clearGrammarOverrides()
+ atom.syntax.clearProperties()
# used to reset keymap after each spec
bindingSetsToRestore = _.clone(keymap.bindingSets)
bindingSetsByFirstKeystrokeToRestore = _.clone(keymap.bindingSetsByFirstKeystroke)
# reset config before each spec; don't load or save from/to `config.json`
- window.config = new Config()
+ config = new Config()
+ config.packageDirPaths.unshift(fixturePackagesPath)
spyOn(config, 'load')
spyOn(config, 'save')
config.set "editor.fontFamily", "Courier"
@@ -57,6 +58,8 @@ beforeEach ->
config.set "editor.autoIndent", false
config.set "core.disabledPackages", ["package-that-throws-an-exception"]
config.save.reset()
+ atom.config = config
+ window.config = config
# make editor display updates synchronous
spyOn(Editor.prototype, 'requestDisplayUpdate').andCallFake -> @updateDisplay()
diff --git a/spec/theme-manager-spec.coffee b/spec/theme-manager-spec.coffee
index 43f8185e6..d5d5cc1b3 100644
--- a/spec/theme-manager-spec.coffee
+++ b/spec/theme-manager-spec.coffee
@@ -1,4 +1,5 @@
-{$} = require 'atom'
+path = require 'path'
+{$, $$, fs, RootView} = require 'atom'
ThemeManager = require '../src/theme-manager'
AtomPackage = require '../src/atom-package'
@@ -73,3 +74,81 @@ describe "ThemeManager", ->
expect(loadHandler).toHaveBeenCalled()
expect(loadHandler.mostRecentCall.args[0]).toBeInstanceOf AtomPackage
+
+ describe "requireStylesheet(path)", ->
+ it "synchronously loads css at the given path and installs a style tag for it in the head", ->
+ cssPath = project.resolve('css.css')
+ lengthBefore = $('head style').length
+
+ themeManager.requireStylesheet(cssPath)
+ expect($('head style').length).toBe lengthBefore + 1
+
+ element = $('head style[id*="css.css"]')
+ expect(element.attr('id')).toBe cssPath
+ expect(element.text()).toBe fs.read(cssPath)
+
+ # doesn't append twice
+ themeManager.requireStylesheet(cssPath)
+ expect($('head style').length).toBe lengthBefore + 1
+
+ $('head style[id*="css.css"]').remove()
+
+ it "synchronously loads and parses less files at the given path and installs a style tag for it in the head", ->
+ lessPath = project.resolve('sample.less')
+ lengthBefore = $('head style').length
+ themeManager.requireStylesheet(lessPath)
+ expect($('head style').length).toBe lengthBefore + 1
+
+ element = $('head style[id*="sample.less"]')
+ expect(element.attr('id')).toBe lessPath
+ expect(element.text()).toBe """
+ #header {
+ color: #4d926f;
+ }
+ h2 {
+ color: #4d926f;
+ }
+
+ """
+
+ # doesn't append twice
+ themeManager.requireStylesheet(lessPath)
+ expect($('head style').length).toBe lengthBefore + 1
+ $('head style[id*="sample.less"]').remove()
+
+ it "supports requiring css and less stylesheets without an explicit extension", ->
+ themeManager.requireStylesheet path.join(__dirname, 'fixtures', 'css')
+ expect($('head style[id*="css.css"]').attr('id')).toBe project.resolve('css.css')
+ themeManager.requireStylesheet path.join(__dirname, 'fixtures', 'sample')
+ expect($('head style[id*="sample.less"]').attr('id')).toBe project.resolve('sample.less')
+
+ $('head style[id*="css.css"]').remove()
+ $('head style[id*="sample.less"]').remove()
+
+ describe ".removeStylesheet(path)", ->
+ it "removes styling applied by given stylesheet path", ->
+ cssPath = require.resolve('./fixtures/css.css')
+
+ expect($(document.body).css('font-weight')).not.toBe("bold")
+ themeManager.requireStylesheet(cssPath)
+ expect($(document.body).css('font-weight')).toBe("bold")
+ themeManager.removeStylesheet(cssPath)
+ expect($(document.body).css('font-weight')).not.toBe("bold")
+
+ describe "base stylesheet loading", ->
+ beforeEach ->
+ window.rootView = new RootView
+ rootView.append $$ -> @div class: 'editor'
+ rootView.attachToDom()
+ themeManager.load()
+
+ it "loads the correct values from the theme's ui-variables file", ->
+ config.set('core.themes', ['theme-with-ui-variables'])
+
+ # an override loaded in the base css
+ expect(rootView.css("background-color")).toBe "rgb(0, 0, 255)"
+
+ # from within the theme itself
+ expect($(".editor").css("padding-top")).toBe "150px"
+ expect($(".editor").css("padding-right")).toBe "150px"
+ expect($(".editor").css("padding-bottom")).toBe "150px"
diff --git a/spec/window-spec.coffee b/spec/window-spec.coffee
index 1522d6ec4..a536d0ca6 100644
--- a/spec/window-spec.coffee
+++ b/spec/window-spec.coffee
@@ -75,66 +75,6 @@ describe "Window", ->
expect(window.onbeforeunload(new Event('beforeunload'))).toBeFalsy()
expect(atom.confirmSync).toHaveBeenCalled()
- describe "requireStylesheet(path)", ->
- it "synchronously loads css at the given path and installs a style tag for it in the head", ->
- cssPath = project.resolve('css.css')
- lengthBefore = $('head style').length
-
- requireStylesheet(cssPath)
- expect($('head style').length).toBe lengthBefore + 1
-
- element = $('head style[id*="css.css"]')
- expect(element.attr('id')).toBe cssPath
- expect(element.text()).toBe fs.read(cssPath)
-
- # doesn't append twice
- requireStylesheet(cssPath)
- expect($('head style').length).toBe lengthBefore + 1
-
- $('head style[id*="css.css"]').remove()
-
- it "synchronously loads and parses less files at the given path and installs a style tag for it in the head", ->
- lessPath = project.resolve('sample.less')
- lengthBefore = $('head style').length
- requireStylesheet(lessPath)
- expect($('head style').length).toBe lengthBefore + 1
-
- element = $('head style[id*="sample.less"]')
- expect(element.attr('id')).toBe lessPath
- expect(element.text()).toBe """
- #header {
- color: #4d926f;
- }
- h2 {
- color: #4d926f;
- }
-
- """
-
- # doesn't append twice
- requireStylesheet(lessPath)
- expect($('head style').length).toBe lengthBefore + 1
- $('head style[id*="sample.less"]').remove()
-
- it "supports requiring css and less stylesheets without an explicit extension", ->
- requireStylesheet path.join(__dirname, 'fixtures', 'css')
- expect($('head style[id*="css.css"]').attr('id')).toBe project.resolve('css.css')
- requireStylesheet path.join(__dirname, 'fixtures', 'sample')
- expect($('head style[id*="sample.less"]').attr('id')).toBe project.resolve('sample.less')
-
- $('head style[id*="css.css"]').remove()
- $('head style[id*="sample.less"]').remove()
-
- describe ".removeStylesheet(path)", ->
- it "removes styling applied by given stylesheet path", ->
- cssPath = require.resolve('./fixtures/css.css')
-
- expect($(document.body).css('font-weight')).not.toBe("bold")
- requireStylesheet(cssPath)
- expect($(document.body).css('font-weight')).toBe("bold")
- removeStylesheet(cssPath)
- expect($(document.body).css('font-weight')).not.toBe("bold")
-
describe ".unloadEditorWindow()", ->
it "saves the serialized state of the window so it can be deserialized after reload", ->
rootViewState = rootView.serialize()
@@ -156,38 +96,6 @@ describe "Window", ->
expect(buffer.subscriptionCount()).toBe 0
- describe ".deserialize(state)", ->
- class Foo
- @deserialize: ({name}) -> new Foo(name)
- constructor: (@name) ->
-
- beforeEach ->
- registerDeserializer(Foo)
-
- afterEach ->
- unregisterDeserializer(Foo)
-
- it "calls deserialize on the deserializer for the given state object, or returns undefined if one can't be found", ->
- spyOn(console, 'warn')
- object = deserialize({ deserializer: 'Foo', name: 'Bar' })
- expect(object.name).toBe 'Bar'
- expect(deserialize({ deserializer: 'Bogus' })).toBeUndefined()
-
- describe "when the deserializer has a version", ->
- beforeEach ->
- Foo.version = 2
-
- describe "when the deserialized state has a matching version", ->
- it "attempts to deserialize the state", ->
- object = deserialize({ deserializer: 'Foo', version: 2, name: 'Bar' })
- expect(object.name).toBe 'Bar'
-
- describe "when the deserialized state has a non-matching version", ->
- it "returns undefined", ->
- expect(deserialize({ deserializer: 'Foo', version: 3, name: 'Bar' })).toBeUndefined()
- expect(deserialize({ deserializer: 'Foo', version: 1, name: 'Bar' })).toBeUndefined()
- expect(deserialize({ deserializer: 'Foo', name: 'Bar' })).toBeUndefined()
-
describe "drag and drop", ->
buildDragEvent = (type, files) ->
dataTransfer =
@@ -206,7 +114,7 @@ describe "Window", ->
it "opens it", ->
spyOn(atom, "open")
event = buildDragEvent("drop", [ {path: "/fake1"}, {path: "/fake2"} ])
- window.onDrop(event)
+ $(document).trigger(event)
expect(atom.open.callCount).toBe 1
expect(atom.open.argsForCall[0][0]).toEqual pathsToOpen: ['/fake1', '/fake2']
@@ -214,7 +122,7 @@ describe "Window", ->
it "does nothing", ->
spyOn(atom, "open")
event = buildDragEvent("drop", [])
- window.onDrop(event)
+ $(document).trigger(event)
expect(atom.open).not.toHaveBeenCalled()
describe "when a link is clicked", ->
diff --git a/src/atom-package.coffee b/src/atom-package.coffee
index 1074eca48..641f67b39 100644
--- a/src/atom-package.coffee
+++ b/src/atom-package.coffee
@@ -83,7 +83,8 @@ class AtomPackage extends Package
activateStylesheets: ->
type = if @metadata.theme then 'theme' else 'bundled'
- applyStylesheet(stylesheetPath, content, type) for [stylesheetPath, content] in @stylesheets
+ for [stylesheetPath, content] in @stylesheets
+ atom.themes.applyStylesheet(stylesheetPath, content, type)
activateResources: ->
keymap.add(keymapPath, map) for [keymapPath, map] in @keymaps
@@ -113,7 +114,8 @@ class AtomPackage extends Package
fsUtils.listSync(menusDirPath, ['cson', 'json'])
loadStylesheets: ->
- @stylesheets = @getStylesheetPaths().map (stylesheetPath) -> [stylesheetPath, loadStylesheet(stylesheetPath)]
+ @stylesheets = @getStylesheetPaths().map (stylesheetPath) ->
+ [stylesheetPath, atom.themes.loadStylesheet(stylesheetPath)]
getStylesheetsPath: ->
path.join(@path, @constructor.stylesheetsDir)
@@ -165,17 +167,17 @@ class AtomPackage extends Package
syntax.removeGrammar(grammar) for grammar in @grammars
syntax.removeProperties(scopedPropertiesPath) for [scopedPropertiesPath] in @scopedProperties
keymap.remove(keymapPath) for [keymapPath] in @keymaps
- removeStylesheet(stylesheetPath) for [stylesheetPath] in @stylesheets
+ atom.themes.removeStylesheet(stylesheetPath) for [stylesheetPath] in @stylesheets
reloadStylesheets: ->
oldSheets = _.clone(@stylesheets)
@loadStylesheets()
- removeStylesheet(stylesheetPath) for [stylesheetPath] in oldSheets
+ atom.themes.removeStylesheet(stylesheetPath) for [stylesheetPath] in oldSheets
@reloadStylesheet(stylesheetPath, content) for [stylesheetPath, content] in @stylesheets
reloadStylesheet: (stylesheetPath, content) ->
type = if @metadata.theme then 'theme' else 'bundled'
- window.applyStylesheet(stylesheetPath, content, type)
+ atom.themes.applyStylesheet(stylesheetPath, content, type)
requireMainModule: ->
return @mainModule if @mainModule?
diff --git a/src/atom.coffee b/src/atom.coffee
index 723f9a7f4..3206081c3 100644
--- a/src/atom.coffee
+++ b/src/atom.coffee
@@ -10,155 +10,140 @@ path = require 'path'
dialog = remote.require 'dialog'
app = remote.require 'app'
{Document} = require 'telepath'
-ThemeManager = require './theme-manager'
-ContextMenuManager = require './context-menu-manager'
+DeserializerManager = require './deserializer-manager'
+Subscriber = require './subscriber'
-window.atom =
- loadedPackages: {}
- activePackages: {}
- packageStates: {}
- themes: new ThemeManager()
- contextMenu: new ContextMenuManager(remote.getCurrentWindow().loadSettings.devMode)
+# Public: Atom global for dealing with packages, themes, menus, and the window.
+#
+# An instance of this class is always available as the `atom` global.
+module.exports =
+class Atom
+ _.extend @prototype, Subscriber
- getLoadSettings: ->
- @getCurrentWindow().loadSettings
+ constructor: ->
+ @rootViewParentSelector = 'body'
+ @deserializers = new DeserializerManager()
+
+ initialize: ->
+ @unsubscribe()
+
+ Config = require './config'
+ Keymap = require './keymap'
+ PackageManager = require './package-manager'
+ Pasteboard = require './pasteboard'
+ Syntax = require './syntax'
+ ThemeManager = require './theme-manager'
+ ContextMenuManager = require './context-menu-manager'
+
+ @packages = new PackageManager()
+
+ #TODO Remove once packages have been updated to not touch atom.packageStates directly
+ @__defineGetter__ 'packageStates', => @packages.packageStates
+ @__defineSetter__ 'packageStates', (packageStates) => @packages.packageStates = packageStates
+
+ @subscribe @packages, 'loaded', => @watchThemes()
+ @themes = new ThemeManager()
+ @contextMenu = new ContextMenuManager(@getLoadSettings().devMode)
+ @config = new Config()
+ @pasteboard = new Pasteboard()
+ @keymap = new Keymap()
+ @syntax = deserialize(@getWindowState('syntax')) ? new Syntax()
getCurrentWindow: ->
remote.getCurrentWindow()
- getPackageState: (name) ->
- @packageStates[name]
+ # Public: Get the dimensions of this window.
+ #
+ # Returns an object with x, y, width, and height keys.
+ getDimensions: ->
+ browserWindow = @getCurrentWindow()
+ [x, y] = browserWindow.getPosition()
+ [width, height] = browserWindow.getSize()
+ {x, y, width, height}
- setPackageState: (name, state) ->
- @packageStates[name] = state
-
- activatePackages: ->
- @activatePackage(pack.name) for pack in @getLoadedPackages()
-
- activatePackage: (name, options) ->
- if pack = @loadPackage(name, options)
- @activePackages[pack.name] = pack
- pack.activate(options)
- pack
-
- deactivatePackages: ->
- @deactivatePackage(pack.name) for pack in @getActivePackages()
-
- deactivatePackage: (name) ->
- if pack = @getActivePackage(name)
- @setPackageState(pack.name, state) if state = pack.serialize?()
- pack.deactivate()
- delete @activePackages[pack.name]
+ # Public: Set the dimensions of the window.
+ #
+ # The window will be centered if either the x or y coordinate is not set
+ # in the dimensions parameter.
+ #
+ # * dimensions:
+ # + x:
+ # The new x coordinate.
+ # + y:
+ # The new y coordinate.
+ # + width:
+ # The new width.
+ # + height:
+ # The new height.
+ setDimensions: ({x, y, width, height}) ->
+ browserWindow = @getCurrentWindow()
+ browserWindow.setSize(width, height)
+ if x? and y?
+ browserWindow.setPosition(x, y)
else
- throw new Error("No active package for name '#{name}'")
+ browserWindow.center()
- getActivePackage: (name) ->
- @activePackages[name]
+ restoreDimensions: (defaultDimensions={width: 800, height: 600})->
+ dimensions = @getWindowState().getObject('dimensions')
+ dimensions = defaultDimensions unless dimensions?.width and dimensions?.height
+ @setDimensions(dimensions)
- isPackageActive: (name) ->
- @getActivePackage(name)?
+ getLoadSettings: ->
+ @getCurrentWindow().loadSettings
- getActivePackages: ->
- _.values(@activePackages)
+ deserializeProject: ->
+ Project = require './project'
+ state = @getWindowState()
+ @project = deserialize(state.get('project'))
+ unless @project?
+ @project = new Project(@getLoadSettings().initialPath)
+ state.set('project', @project.getState())
- loadPackages: ->
- # Ensure atom exports is already in the require cache so the load time
- # of the first package isn't skewed by being the first to require atom
- require '../exports/atom'
+ deserializeRootView: ->
+ RootView = require './root-view'
+ state = @getWindowState()
+ @rootView = deserialize(state.get('rootView'))
+ unless @rootView?
+ @rootView = new RootView()
+ state.set('rootView', @rootView.getState())
+ $(@rootViewParentSelector).append(@rootView)
- @loadPackage(name) for name in @getAvailablePackageNames() when not @isPackageDisabled(name)
- @watchThemes()
+ deserializePackageStates: ->
+ state = @getWindowState()
+ @packages.packageStates = state.getObject('packageStates') ? {}
+ state.remove('packageStates')
- loadPackage: (name, options) ->
- if @isPackageDisabled(name)
- return console.warn("Tried to load disabled package '#{name}'")
-
- if packagePath = @resolvePackagePath(name)
- return pack if pack = @getLoadedPackage(name)
- pack = Package.load(packagePath, options)
- if pack.metadata.theme
- @themes.register(pack)
- else
- @loadedPackages[pack.name] = pack
- pack
- else
- throw new Error("Could not resolve '#{name}' to a package path")
-
- unloadPackage: (name) ->
- if @isPackageActive(name)
- throw new Error("Tried to unload active package '#{name}'")
-
- if pack = @getLoadedPackage(name)
- delete @loadedPackages[pack.name]
- else
- throw new Error("No loaded package for name '#{name}'")
-
- resolvePackagePath: (name) ->
- return name if fsUtils.isDirectorySync(name)
-
- packagePath = fsUtils.resolve(config.packageDirPaths..., name)
- return packagePath if fsUtils.isDirectorySync(packagePath)
-
- packagePath = path.join(window.resourcePath, 'node_modules', name)
- return packagePath if @isInternalPackage(packagePath)
-
- isInternalPackage: (packagePath) ->
- {engines} = Package.loadMetadata(packagePath, true)
- engines?.atom?
-
- getLoadedPackage: (name) ->
- @loadedPackages[name]
-
- isPackageLoaded: (name) ->
- @getLoadedPackage(name)?
-
- getLoadedPackages: ->
- _.values(@loadedPackages)
-
- isPackageDisabled: (name) ->
- _.include(config.get('core.disabledPackages') ? [], name)
-
- getAvailablePackagePaths: ->
- packagePaths = []
-
- for packageDirPath in config.packageDirPaths
- for packagePath in fsUtils.listSync(packageDirPath)
- packagePaths.push(packagePath) if fsUtils.isDirectorySync(packagePath)
-
- for packagePath in fsUtils.listSync(path.join(window.resourcePath, 'node_modules'))
- packagePaths.push(packagePath) if @isInternalPackage(packagePath)
-
- _.uniq(packagePaths)
-
- getAvailablePackageNames: ->
- _.uniq _.map @getAvailablePackagePaths(), (packagePath) -> path.basename(packagePath)
-
- getAvailablePackageMetadata: ->
- packages = []
- for packagePath in atom.getAvailablePackagePaths()
- name = path.basename(packagePath)
- metadata = atom.getLoadedPackage(name)?.metadata ? Package.loadMetadata(packagePath, true)
- packages.push(metadata)
- packages
+ #TODO Remove theses once packages have been migrated
+ getPackageState: (args...) -> @packages.getPackageState(args...)
+ setPackageState: (args...) -> @packages.setPackageState(args...)
+ activatePackages: (args...) -> @packages.activatePackages(args...)
+ activatePackage: (args...) -> @packages.activatePackage(args...)
+ deactivatePackages: (args...) -> @packages.deactivatePackages(args...)
+ deactivatePackage: (args...) -> @packages.deactivatePackage(args...)
+ getActivePackage: (args...) -> @packages.getActivePackage(args...)
+ isPackageActive: (args...) -> @packages.isPackageActive(args...)
+ getActivePackages: (args...) -> @packages.getActivePackages(args...)
+ loadPackages: (args...) -> @packages.loadPackages(args...)
+ loadPackage: (args...) -> @packages.loadPackage(args...)
+ unloadPackage: (args...) -> @packages.unloadPackage(args...)
+ resolvePackagePath: (args...) -> @packages.resolvePackagePath(args...)
+ isInternalPackage: (args...) -> @packages.isInternalPackage(args...)
+ getLoadedPackage: (args...) -> @packages.getLoadedPackage(args...)
+ isPackageLoaded: (args...) -> @packages.isPackageLoaded(args...)
+ getLoadedPackages: (args...) -> @packages.getLoadedPackages(args...)
+ isPackageDisabled: (args...) -> @packages.isPackageDisabled(args...)
+ getAvailablePackagePaths: (args...) -> @packages.getAvailablePackagePaths(args...)
+ getAvailablePackageNames: (args...) -> @packages.getAvailablePackageNames(args...)
+ getAvailablePackageMetadata: (args...)-> @packages.getAvailablePackageMetadata(args...)
loadThemes: ->
@themes.load()
watchThemes: ->
@themes.on 'reloaded', =>
- @reloadBaseStylesheets()
- pack.reloadStylesheets?() for name, pack of @loadedPackages
+ pack.reloadStylesheets?() for name, pack of @getLoadedPackages()
null
- loadBaseStylesheets: ->
- requireStylesheet('bootstrap/less/bootstrap')
- @reloadBaseStylesheets()
-
- reloadBaseStylesheets: ->
- requireStylesheet('../static/atom')
- if nativeStylesheetPath = fsUtils.resolveOnLoadPath(process.platform, ['css', 'less'])
- requireStylesheet(nativeStylesheetPath)
-
open: (options) ->
ipc.sendChannel('open', options)
@@ -210,8 +195,7 @@ window.atom =
close: ->
@getCurrentWindow().close()
- exit: (status) ->
- app.exit(status)
+ exit: (status) -> app.exit(status)
toggleFullScreen: ->
@setFullScreen(!@isFullScreen())
@@ -236,7 +220,7 @@ window.atom =
filename = "editor-#{sha1}"
if filename
- path.join(config.userStoragePath, filename)
+ path.join(@config.userStoragePath, filename)
else
null
@@ -289,8 +273,22 @@ window.atom =
shell.beep()
requireUserInitScript: ->
- userInitScriptPath = path.join(config.configDirPath, "user.coffee")
+ userInitScriptPath = path.join(@config.configDirPath, "user.coffee")
try
require userInitScriptPath if fsUtils.isFileSync(userInitScriptPath)
catch error
console.error "Failed to load `#{userInitScriptPath}`", error.stack, error
+
+ requireWithGlobals: (id, globals={}) ->
+ existingGlobals = {}
+ for key, value of globals
+ existingGlobals[key] = window[key]
+ window[key] = value
+
+ require(id)
+
+ for key, value of existingGlobals
+ if value is undefined
+ delete window[key]
+ else
+ window[key] = value
diff --git a/src/config.coffee b/src/config.coffee
index ffcd24809..1b2466381 100644
--- a/src/config.coffee
+++ b/src/config.coffee
@@ -8,12 +8,6 @@ async = require 'async'
pathWatcher = require 'pathwatcher'
configDirPath = fsUtils.absolute("~/.atom")
-nodeModulesDirPath = path.join(resourcePath, "node_modules")
-bundledKeymapsDirPath = path.join(resourcePath, "keymaps")
-userPackagesDirPath = path.join(configDirPath, "packages")
-userPackageDirPaths = [userPackagesDirPath]
-userPackageDirPaths.unshift(path.join(configDirPath, "dev", "packages")) if atom.getLoadSettings().devMode
-userStoragePath = path.join(configDirPath, "storage")
# Public: Used to access all of Atom's configuration details.
#
@@ -36,23 +30,26 @@ module.exports =
class Config
_.extend @prototype, EventEmitter
- configDirPath: configDirPath
- bundledPackageDirPaths: [nodeModulesDirPath]
- bundledKeymapsDirPath: bundledKeymapsDirPath
- nodeModulesDirPath: nodeModulesDirPath
- packageDirPaths: _.clone(userPackageDirPaths)
- userPackageDirPaths: userPackageDirPaths
- userStoragePath: userStoragePath
- lessSearchPaths: [
- path.join(resourcePath, 'static', 'variables')
- path.join(resourcePath, 'static')
- ]
defaultSettings: null
settings: null
configFileHasErrors: null
# Private: Created during initialization, available as `global.config`
constructor: ->
+ @configDirPath = configDirPath
+ @bundledKeymapsDirPath = path.join(resourcePath, "keymaps")
+ @nodeModulesDirPath = path.join(resourcePath, "node_modules")
+ @bundledPackageDirPaths = [@nodeModulesDirPath]
+ @lessSearchPaths = [
+ path.join(resourcePath, 'static', 'variables')
+ path.join(resourcePath, 'static')
+ ]
+ @packageDirPaths = [path.join(configDirPath, "packages")]
+ if atom.getLoadSettings().devMode
+ @packageDirPaths.unshift(path.join(configDirPath, "dev", "packages"))
+ @userPackageDirPaths = _.clone(@packageDirPaths)
+ @userStoragePath = path.join(configDirPath, "storage")
+
@defaultSettings =
core: _.clone(require('./root-view').configDefaults)
editor: _.clone(require('./editor').configDefaults)
diff --git a/src/deserializer-manager.coffee b/src/deserializer-manager.coffee
new file mode 100644
index 000000000..8fd3bec19
--- /dev/null
+++ b/src/deserializer-manager.coffee
@@ -0,0 +1,38 @@
+{Document} = require 'telepath'
+
+module.exports =
+class DeserializerManager
+ constructor: ->
+ @deserializers = {}
+ @deferredDeserializers = {}
+
+ registerDeserializer: (klasses...) ->
+ @deserializers[klass.name] = klass for klass in klasses
+
+ registerDeferredDeserializer: (name, fn) ->
+ @deferredDeserializers[name] = fn
+
+ unregisterDeserializer: (klasses...) ->
+ delete @deserializers[klass.name] for klass in klasses
+
+ deserialize: (state, params) ->
+ return unless state?
+
+ if deserializer = @getDeserializer(state)
+ stateVersion = state.get?('version') ? state.version
+ return if deserializer.version? and deserializer.version isnt stateVersion
+ if (state instanceof Document) and not deserializer.acceptsDocuments
+ state = state.toObject()
+ deserializer.deserialize(state, params)
+ else
+ console.warn "No deserializer found for", state
+
+ getDeserializer: (state) ->
+ return unless state?
+
+ name = state.get?('deserializer') ? state.deserializer
+ if @deferredDeserializers[name]
+ @deferredDeserializers[name]()
+ delete @deferredDeserializers[name]
+
+ @deserializers[name]
diff --git a/src/package-manager.coffee b/src/package-manager.coffee
new file mode 100644
index 000000000..cc08c6f56
--- /dev/null
+++ b/src/package-manager.coffee
@@ -0,0 +1,129 @@
+EventEmitter = require './event-emitter'
+fsUtils = require './fs-utils'
+_ = require './underscore-extensions'
+Package = require './package'
+path = require 'path'
+
+module.exports =
+class PackageManager
+ _.extend @prototype, EventEmitter
+
+ constructor: ->
+ @loadedPackages = {}
+ @activePackages = {}
+ @packageStates = {}
+
+ getPackageState: (name) ->
+ @packageStates[name]
+
+ setPackageState: (name, state) ->
+ @packageStates[name] = state
+
+ activatePackages: ->
+ @activatePackage(pack.name) for pack in @getLoadedPackages()
+
+ activatePackage: (name, options) ->
+ if pack = @loadPackage(name, options)
+ @activePackages[pack.name] = pack
+ pack.activate(options)
+ pack
+
+ deactivatePackages: ->
+ @deactivatePackage(pack.name) for pack in @getActivePackages()
+
+ deactivatePackage: (name) ->
+ if pack = @getActivePackage(name)
+ @setPackageState(pack.name, state) if state = pack.serialize?()
+ pack.deactivate()
+ delete @activePackages[pack.name]
+ else
+ throw new Error("No active package for name '#{name}'")
+
+ getActivePackage: (name) ->
+ @activePackages[name]
+
+ isPackageActive: (name) ->
+ @getActivePackage(name)?
+
+ getActivePackages: ->
+ _.values(@activePackages)
+
+ loadPackages: ->
+ # Ensure atom exports is already in the require cache so the load time
+ # of the first package isn't skewed by being the first to require atom
+ require '../exports/atom'
+
+ @loadPackage(name) for name in @getAvailablePackageNames() when not @isPackageDisabled(name)
+ @trigger 'loaded'
+
+ loadPackage: (name, options) ->
+ if @isPackageDisabled(name)
+ return console.warn("Tried to load disabled package '#{name}'")
+
+ if packagePath = @resolvePackagePath(name)
+ return pack if pack = @getLoadedPackage(name)
+ pack = Package.load(packagePath, options)
+ if pack.metadata.theme
+ atom.themes.register(pack)
+ else
+ @loadedPackages[pack.name] = pack
+ pack
+ else
+ throw new Error("Could not resolve '#{name}' to a package path")
+
+ unloadPackage: (name) ->
+ if @isPackageActive(name)
+ throw new Error("Tried to unload active package '#{name}'")
+
+ if pack = @getLoadedPackage(name)
+ delete @loadedPackages[pack.name]
+ else
+ throw new Error("No loaded package for name '#{name}'")
+
+ resolvePackagePath: (name) ->
+ return name if fsUtils.isDirectorySync(name)
+
+ packagePath = fsUtils.resolve(config.packageDirPaths..., name)
+ return packagePath if fsUtils.isDirectorySync(packagePath)
+
+ packagePath = path.join(window.resourcePath, 'node_modules', name)
+ return packagePath if @isInternalPackage(packagePath)
+
+ isInternalPackage: (packagePath) ->
+ {engines} = Package.loadMetadata(packagePath, true)
+ engines?.atom?
+
+ getLoadedPackage: (name) ->
+ @loadedPackages[name]
+
+ isPackageLoaded: (name) ->
+ @getLoadedPackage(name)?
+
+ getLoadedPackages: ->
+ _.values(@loadedPackages)
+
+ isPackageDisabled: (name) ->
+ _.include(config.get('core.disabledPackages') ? [], name)
+
+ getAvailablePackagePaths: ->
+ packagePaths = []
+
+ for packageDirPath in config.packageDirPaths
+ for packagePath in fsUtils.listSync(packageDirPath)
+ packagePaths.push(packagePath) if fsUtils.isDirectorySync(packagePath)
+
+ for packagePath in fsUtils.listSync(path.join(window.resourcePath, 'node_modules'))
+ packagePaths.push(packagePath) if @isInternalPackage(packagePath)
+
+ _.uniq(packagePaths)
+
+ getAvailablePackageNames: ->
+ _.uniq _.map @getAvailablePackagePaths(), (packagePath) -> path.basename(packagePath)
+
+ getAvailablePackageMetadata: ->
+ packages = []
+ for packagePath in atom.getAvailablePackagePaths()
+ name = path.basename(packagePath)
+ metadata = atom.getLoadedPackage(name)?.metadata ? Package.loadMetadata(packagePath, true)
+ packages.push(metadata)
+ packages
diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee
index 5ae6ff6f7..3c4b71e48 100644
--- a/src/theme-manager.coffee
+++ b/src/theme-manager.coffee
@@ -4,7 +4,7 @@ Package = require './package'
AtomPackage = require './atom-package'
_ = require './underscore-extensions'
-
+$ = require './jquery-extensions'
fsUtils = require './fs-utils'
# Private: Handles discovering and loading available themes.
@@ -15,6 +15,7 @@ class ThemeManager
constructor: ->
@loadedThemes = []
@activeThemes = []
+ @lessCache = null
# Internal-only:
register: (theme) ->
@@ -33,9 +34,85 @@ class ThemeManager
getLoadedThemes: ->
_.clone(@loadedThemes)
+ # Internal-only:
+ loadBaseStylesheets: ->
+ @requireStylesheet('bootstrap/less/bootstrap')
+ @reloadBaseStylesheets()
+
+ # Internal-only:
+ reloadBaseStylesheets: ->
+ @requireStylesheet('../static/atom')
+ if nativeStylesheetPath = fsUtils.resolveOnLoadPath(process.platform, ['css', 'less'])
+ @requireStylesheet(nativeStylesheetPath)
+
+ # Internal-only:
+ stylesheetElementForId: (id) ->
+ $("""head style[id="#{id}"]""")
+
+ # Internal-only:
+ resolveStylesheet: (stylesheetPath) ->
+ if path.extname(stylesheetPath).length > 0
+ fsUtils.resolveOnLoadPath(stylesheetPath)
+ else
+ fsUtils.resolveOnLoadPath(stylesheetPath, ['css', 'less'])
+
+ # Public: resolves and applies the stylesheet specified by the path.
+ #
+ # * stylesheetPath: String. Can be an absolute path or the name of a CSS or
+ # LESS file in the stylesheets path.
+ #
+ # Returns the absolute path to the stylesheet
+ requireStylesheet: (stylesheetPath) ->
+ if fullPath = @resolveStylesheet(stylesheetPath)
+ content = @loadStylesheet(fullPath)
+ @applyStylesheet(fullPath, content)
+ else
+ throw new Error("Could not find a file at path '#{stylesheetPath}'")
+
+ fullPath
+
+ # Internal-only:
+ loadStylesheet: (stylesheetPath) ->
+ if path.extname(stylesheetPath) is '.less'
+ @loadLessStylesheet(stylesheetPath)
+ else
+ fsUtils.read(stylesheetPath)
+
+ # Internal-only:
+ loadLessStylesheet: (lessStylesheetPath) ->
+ unless lessCache?
+ LessCompileCache = require './less-compile-cache'
+ @lessCache = new LessCompileCache()
+
+ try
+ @lessCache.read(lessStylesheetPath)
+ catch e
+ console.error """
+ Error compiling less stylesheet: #{lessStylesheetPath}
+ Line number: #{e.line}
+ #{e.message}
+ """
+
+ # Internal-only:
+ removeStylesheet: (stylesheetPath) ->
+ unless fullPath = @resolveStylesheet(stylesheetPath)
+ throw new Error("Could not find a file at path '#{stylesheetPath}'")
+ @stylesheetElementForId(fullPath).remove()
+
+ # Internal-only:
+ applyStylesheet: (id, text, ttype = 'bundled') ->
+ styleElement = @stylesheetElementForId(id)
+ if styleElement.length
+ styleElement.text(text)
+ else
+ if $("head style.#{ttype}").length
+ $("head style.#{ttype}:last").after ""
+ else
+ $("head").append ""
+
# Internal-only:
unload: ->
- removeStylesheet(@userStylesheetPath) if @userStylesheetPath?
+ @removeStylesheet(@userStylesheetPath) if @userStylesheetPath?
theme.deactivate() while theme = @activeThemes.pop()
# Internal-only:
@@ -50,7 +127,7 @@ class ThemeManager
@activateTheme(themeName) for themeName in themeNames
@loadUserStylesheet()
-
+ @reloadBaseStylesheets()
@trigger('reloaded')
# Private:
@@ -118,5 +195,5 @@ class ThemeManager
loadUserStylesheet: ->
if userStylesheetPath = @getUserStylesheetPath()
@userStylesheetPath = userStylesheetPath
- userStylesheetContents = loadStylesheet(userStylesheetPath)
- applyStylesheet(userStylesheetPath, userStylesheetContents, 'userTheme')
+ userStylesheetContents = @loadStylesheet(userStylesheetPath)
+ @applyStylesheet(userStylesheetPath, userStylesheetContents, 'userTheme')
diff --git a/src/window-bootstrap.coffee b/src/window-bootstrap.coffee
index bccf2ee92..15da3237e 100644
--- a/src/window-bootstrap.coffee
+++ b/src/window-bootstrap.coffee
@@ -1,9 +1,10 @@
# Like sands through the hourglass, so are the days of our lives.
startTime = new Date().getTime()
-require './atom'
require './window'
+Atom = require './atom'
+window.atom = new Atom()
window.setUpEnvironment('editor')
window.startEditorWindow()
console.log "Window load time: #{new Date().getTime() - startTime}ms"
diff --git a/src/window-event-handler.coffee b/src/window-event-handler.coffee
index 33b6f2cd5..60e157b6d 100644
--- a/src/window-event-handler.coffee
+++ b/src/window-event-handler.coffee
@@ -1,7 +1,7 @@
$ = require './jquery-extensions'
_ = require './underscore-extensions'
ipc = require 'ipc'
-remote = require 'remote'
+shell = require 'shell'
Subscriber = require './subscriber'
fsUtils = require './fs-utils'
@@ -20,27 +20,43 @@ class WindowEventHandler
$(atom.contextMenu.activeElement).trigger(command, args...)
@subscribe $(window), 'focus', -> $("body").removeClass('is-blurred')
+
@subscribe $(window), 'blur', -> $("body").addClass('is-blurred')
+
@subscribe $(window), 'window:open-path', (event, {pathToOpen, initialLine}) ->
- rootView?.open(pathToOpen, {initialLine}) unless fsUtils.isDirectorySync(pathToOpen)
+ atom.rootView?.open(pathToOpen, {initialLine}) unless fsUtils.isDirectorySync(pathToOpen)
+
@subscribe $(window), 'beforeunload', =>
- confirmed = rootView?.confirmClose()
- atom.hide() if confirmed and not @reloadRequested and remote.getCurrentWindow().isWebViewFocused()
+ confirmed = atom.rootView?.confirmClose()
+ atom.hide() if confirmed and not @reloadRequested and atom.getCurrentWindow().isWebViewFocused()
@reloadRequested = false
confirmed
+
+ @subscribe $(window), 'unload', ->
+ atom.getWindowState().set('dimensions', atom.getDimensions())
+
@subscribeToCommand $(window), 'window:toggle-full-screen', => atom.toggleFullScreen()
+
@subscribeToCommand $(window), 'window:close', => atom.close()
+
@subscribeToCommand $(window), 'window:reload', =>
@reloadRequested = true
atom.reload()
+
@subscribeToCommand $(window), 'window:toggle-dev-tools', => atom.toggleDevTools()
@subscribeToCommand $(document), 'core:focus-next', @focusNext
+
@subscribeToCommand $(document), 'core:focus-previous', @focusPrevious
- @subscribe $(document), 'keydown', keymap.handleKeyEvent
+ @subscribe $(document), 'keydown', atom.keymap.handleKeyEvent
+
+ @subscribe $(document), 'drop', (e) ->
+ e.preventDefault()
+ e.stopPropagation()
+ pathsToOpen = _.pluck(e.originalEvent.dataTransfer.files, 'path')
+ atom.open({pathsToOpen}) if pathsToOpen.length > 0
- @subscribe $(document), 'drop', onDrop
@subscribe $(document), 'dragover', (e) ->
e.preventDefault()
e.stopPropagation()
@@ -54,7 +70,7 @@ class WindowEventHandler
openLink: (event) =>
location = $(event.target).attr('href')
if location and location[0] isnt '#' and /^https?:\/\//.test(location)
- require('shell').openExternal(location)
+ shell.openExternal(location)
false
eachTabIndexedElement: (callback) ->
diff --git a/src/window.coffee b/src/window.coffee
index 337a3704b..72c29d1ec 100644
--- a/src/window.coffee
+++ b/src/window.coffee
@@ -1,17 +1,9 @@
-fsUtils = require './fs-utils'
path = require 'path'
-telepath = require 'telepath'
$ = require './jquery-extensions'
_ = require './underscore-extensions'
-remote = require 'remote'
ipc = require 'ipc'
WindowEventHandler = require './window-event-handler'
-deserializers = {}
-deferredDeserializers = {}
-defaultWindowDimensions = {width: 800, height: 600}
-lessCache = null
-
### Internal ###
windowEventHandler = null
@@ -28,19 +20,13 @@ displayWindow = ->
# This method is called in any window needing a general environment, including specs
window.setUpEnvironment = (windowMode) ->
atom.windowMode = windowMode
- window.resourcePath = remote.getCurrentWindow().loadSettings.resourcePath
-
- Config = require './config'
- Syntax = require './syntax'
- Pasteboard = require './pasteboard'
- Keymap = require './keymap'
-
- window.rootViewParentSelector = 'body'
- window.config = new Config
- window.syntax = deserialize(atom.getWindowState('syntax')) ? new Syntax
- window.pasteboard = new Pasteboard
- window.keymap = new Keymap()
-
+ window.resourcePath = atom.getLoadSettings().resourcePath
+ atom.initialize()
+ #TODO remove once all packages use the atom global
+ window.config = atom.config
+ window.syntax = atom.syntax
+ window.pasteboard = atom.pasteboard
+ window.keymap = atom.keymap
# Set up the default event handlers and menus for a non-editor windows.
#
@@ -50,8 +36,8 @@ window.setUpEnvironment = (windowMode) ->
# This should only be called after setUpEnvironment() has been called.
window.setUpDefaultEvents = ->
windowEventHandler = new WindowEventHandler
- keymap.loadBundledKeymaps()
- ipc.sendChannel 'update-application-menu', keymap.keystrokesByCommandForSelector('body')
+ atom.keymap.loadBundledKeymaps()
+ ipc.sendChannel 'update-application-menu', atom.keymap.keystrokesByCommandForSelector('body')
# This method is only called when opening a real application window
window.startEditorWindow = ->
@@ -60,16 +46,16 @@ window.startEditorWindow = ->
windowEventHandler = new WindowEventHandler
restoreDimensions()
- config.load()
- keymap.loadBundledKeymaps()
- atom.loadBaseStylesheets()
- atom.loadPackages()
- atom.loadThemes()
+ atom.config.load()
+ atom.keymap.loadBundledKeymaps()
+ atom.themes.loadBaseStylesheets()
+ atom.packages.loadPackages()
+ atom.themes.load()
deserializeEditorWindow()
- atom.activatePackages()
- keymap.loadUserKeymaps()
+ atom.packages.activatePackages()
+ atom.keymap.loadUserKeymaps()
atom.requireUserInitScript()
- ipc.sendChannel 'update-application-menu', keymap.keystrokesByCommandForSelector('body')
+ ipc.sendChannel 'update-application-menu', atom.keymap.keystrokesByCommandForSelector('body')
$(window).on 'unload', ->
$(document.body).hide()
unloadEditorWindow()
@@ -78,188 +64,58 @@ window.startEditorWindow = ->
displayWindow()
window.unloadEditorWindow = ->
- return if not project and not rootView
+ return if not atom.project and not atom.rootView
windowState = atom.getWindowState()
- windowState.set('project', project.serialize())
- windowState.set('syntax', syntax.serialize())
- windowState.set('rootView', rootView.serialize())
- atom.deactivatePackages()
- windowState.set('packageStates', atom.packageStates)
+ windowState.set('project', atom.project.serialize())
+ windowState.set('syntax', atom.syntax.serialize())
+ windowState.set('rootView', atom.rootView.serialize())
+ atom.packages.deactivatePackages()
+ windowState.set('packageStates', atom.packages.packageStates)
atom.saveWindowState()
- rootView.remove()
- project.destroy()
+ atom.rootView.remove()
+ atom.project.destroy()
windowEventHandler?.unsubscribe()
- lessCache?.destroy()
window.rootView = null
window.project = null
-window.installAtomCommand = (callback) ->
+installAtomCommand = (callback) ->
commandPath = path.join(window.resourcePath, 'atom.sh')
require('./command-installer').install(commandPath, callback)
-window.installApmCommand = (callback) ->
+installApmCommand = (callback) ->
commandPath = path.join(window.resourcePath, 'node_modules', '.bin', 'apm')
require('./command-installer').install(commandPath, callback)
-window.onDrop = (e) ->
- e.preventDefault()
- e.stopPropagation()
- pathsToOpen = _.pluck(e.originalEvent.dataTransfer.files, 'path')
- atom.open({pathsToOpen}) if pathsToOpen.length > 0
-
window.deserializeEditorWindow = ->
- RootView = require './root-view'
- Project = require './project'
+ atom.deserializePackageStates()
+ atom.deserializeProject()
+ window.project = atom.project
+ atom.deserializeRootView()
+ window.rootView = atom.rootView
- windowState = atom.getWindowState()
+window.getDimensions = -> atom.getDimensions()
- atom.packageStates = windowState.getObject('packageStates') ? {}
- windowState.remove('packageStates')
+window.setDimensions = (args...) -> atom.setDimensions(args...)
- window.project = deserialize(windowState.get('project'))
- unless window.project?
- window.project = new Project(atom.getLoadSettings().initialPath)
- windowState.set('project', window.project.getState())
-
- window.rootView = deserialize(windowState.get('rootView'))
- unless window.rootView?
- window.rootView = new RootView()
- windowState.set('rootView', window.rootView.getState())
-
- $(rootViewParentSelector).append(rootView)
-
- project.on 'path-changed', ->
- projectPath = project.getPath()
- atom.getLoadSettings().initialPath = projectPath
-
-window.stylesheetElementForId = (id) ->
- $("""head style[id="#{id}"]""")
-
-window.resolveStylesheet = (stylesheetPath) ->
- if path.extname(stylesheetPath).length > 0
- fsUtils.resolveOnLoadPath(stylesheetPath)
- else
- fsUtils.resolveOnLoadPath(stylesheetPath, ['css', 'less'])
-
-# Public: resolves and applies the stylesheet specified by the path.
-#
-# * stylesheetPath: String. Can be an absolute path or the name of a CSS or
-# LESS file in the stylesheets path.
-#
-# Returns the absolute path to the stylesheet
-window.requireStylesheet = (stylesheetPath) ->
- if fullPath = window.resolveStylesheet(stylesheetPath)
- content = window.loadStylesheet(fullPath)
- window.applyStylesheet(fullPath, content)
- else
- throw new Error("Could not find a file at path '#{stylesheetPath}'")
-
- fullPath
-
-window.loadStylesheet = (stylesheetPath) ->
- if path.extname(stylesheetPath) is '.less'
- loadLessStylesheet(stylesheetPath)
- else
- fsUtils.read(stylesheetPath)
-
-window.loadLessStylesheet = (lessStylesheetPath) ->
- unless lessCache?
- LessCompileCache = require './less-compile-cache'
- lessCache = new LessCompileCache()
-
- try
- lessCache.read(lessStylesheetPath)
- catch e
- console.error """
- Error compiling less stylesheet: #{lessStylesheetPath}
- Line number: #{e.line}
- #{e.message}
- """
-
-window.removeStylesheet = (stylesheetPath) ->
- unless fullPath = window.resolveStylesheet(stylesheetPath)
- throw new Error("Could not find a file at path '#{stylesheetPath}'")
- window.stylesheetElementForId(fullPath).remove()
-
-window.applyStylesheet = (id, text, ttype = 'bundled') ->
- styleElement = window.stylesheetElementForId(id)
- if styleElement.length
- styleElement.text(text)
- else
- if $("head style.#{ttype}").length
- $("head style.#{ttype}:last").after ""
- else
- $("head").append ""
-
-window.getDimensions = ->
- browserWindow = remote.getCurrentWindow()
- [x, y] = browserWindow.getPosition()
- [width, height] = browserWindow.getSize()
- {x, y, width, height}
-
-window.setDimensions = ({x, y, width, height}) ->
- browserWindow = remote.getCurrentWindow()
- browserWindow.setSize(width, height)
- if x? and y?
- browserWindow.setPosition(x, y)
- else
- browserWindow.center()
-
-window.restoreDimensions = ->
- dimensions = atom.getWindowState().getObject('dimensions')
- dimensions = defaultWindowDimensions unless dimensions?.width and dimensions?.height
- window.setDimensions(dimensions)
- $(window).on 'unload', -> atom.getWindowState().set('dimensions', window.getDimensions())
+window.restoreDimensions = (args...) -> atom.restoreDimensions(args...)
window.onerror = ->
atom.openDevTools()
window.registerDeserializers = (args...) ->
- registerDeserializer(arg) for arg in args
-
-window.registerDeserializer = (klass) ->
- deserializers[klass.name] = klass
-
-window.registerDeferredDeserializer = (name, fn) ->
- deferredDeserializers[name] = fn
-
-window.unregisterDeserializer = (klass) ->
- delete deserializers[klass.name]
-
-window.deserialize = (state, params) ->
- return unless state?
- if deserializer = getDeserializer(state)
- stateVersion = state.get?('version') ? state.version
- return if deserializer.version? and deserializer.version isnt stateVersion
- if (state instanceof telepath.Document) and not deserializer.acceptsDocuments
- state = state.toObject()
- deserializer.deserialize(state, params)
- else
- console.warn "No deserializer found for", state
-
-window.getDeserializer = (state) ->
- return unless state?
-
- name = state.get?('deserializer') ? state.deserializer
- if deferredDeserializers[name]
- deferredDeserializers[name]()
- delete deferredDeserializers[name]
-
- deserializers[name]
-
-window.requireWithGlobals = (id, globals={}) ->
- existingGlobals = {}
- for key, value of globals
- existingGlobals[key] = window[key]
- window[key] = value
-
- require(id)
-
- for key, value of existingGlobals
- if value is undefined
- delete window[key]
- else
- window[key] = value
+ atom.deserializers.registerDeserializer(args...)
+window.registerDeserializer = (args...) ->
+ atom.deserializers.registerDeserializer(args...)
+window.registerDeferredDeserializer = (args...) ->
+ atom.deserializers.registerDeferredDeserializer(args...)
+window.unregisterDeserializer = (args...) ->
+ atom.deserializers.unregisterDeserializer(args...)
+window.deserialize = (args...) ->
+ atom.deserializers.deserialize(args...)
+window.getDeserializer = (args...) ->
+ atom.deserializer.getDeserializer(args...)
+window.requireWithGlobals = (args...) ->
+ atom.requireWithGlobals(args...)
window.measure = (description, fn) ->
start = new Date().getTime()