mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-09-21 07:58:04 +03:00
commit
46762327c6
@ -1,4 +1,5 @@
|
||||
require '../src/atom'
|
||||
Atom = require '../src/atom'
|
||||
window.atom = new Atom()
|
||||
{runSpecSuite} = require '../spec/jasmine-helper'
|
||||
|
||||
atom.openDevTools()
|
||||
|
@ -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")
|
||||
|
33
spec/deserializer-manager-spec.coffee
Normal file
33
spec/deserializer-manager-spec.coffee
Normal file
@ -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()
|
@ -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"
|
||||
|
@ -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()
|
||||
|
@ -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"
|
||||
|
@ -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", ->
|
||||
|
@ -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?
|
||||
|
260
src/atom.coffee
260
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
|
||||
|
@ -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)
|
||||
|
38
src/deserializer-manager.coffee
Normal file
38
src/deserializer-manager.coffee
Normal file
@ -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]
|
129
src/package-manager.coffee
Normal file
129
src/package-manager.coffee
Normal file
@ -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
|
@ -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 "<style class='#{ttype}' id='#{id}'>#{text}</style>"
|
||||
else
|
||||
$("head").append "<style class='#{ttype}' id='#{id}'>#{text}</style>"
|
||||
|
||||
# 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')
|
||||
|
@ -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"
|
||||
|
@ -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) ->
|
||||
|
@ -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 "<style class='#{ttype}' id='#{id}'>#{text}</style>"
|
||||
else
|
||||
$("head").append "<style class='#{ttype}' id='#{id}'>#{text}</style>"
|
||||
|
||||
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()
|
||||
|
Loading…
Reference in New Issue
Block a user