Files
atom/src/app/atom.coffee
2013-04-26 15:36:13 -07:00

298 lines
8.9 KiB
CoffeeScript

fsUtils = require 'fs-utils'
_ = require 'underscore'
Package = require 'package'
Theme = require 'theme'
messageIdCounter = 1
originalSendMessageToBrowserProcess = atom.sendMessageToBrowserProcess
_.extend atom,
exitWhenDone: window.location.params.exitWhenDone
devMode: window.location.params.devMode
loadedThemes: []
pendingBrowserProcessCallbacks: {}
loadedPackages: []
activePackages: []
packageStates: {}
presentingModal: false
pendingModals: [[]]
getPathToOpen: ->
@getWindowState('pathToOpen') ? window.location.params.pathToOpen
getPackageState: (name) ->
@packageStates[name]
setPackageState: (name, state) ->
@packageStates[name] = state
activatePackages: ->
@activatePackage(pack.path) for pack in @getLoadedPackages()
activatePackage: (id, options) ->
if pack = @loadPackage(id, options)
@activePackages.push(pack)
pack.activate(options)
pack
deactivatePackages: ->
@deactivatePackage(pack.path) for pack in @getActivePackages()
deactivatePackage: (id) ->
if pack = @getActivePackage(id)
@setPackageState(pack.name, state) if state = pack.serialize?()
pack.deactivate()
_.remove(@activePackages, pack)
else
throw new Error("No active package for id '#{id}'")
getActivePackage: (id) ->
if path = @resolvePackagePath(id)
_.detect @activePackages, (pack) -> pack.path is path
isPackageActive: (id) ->
if path = @resolvePackagePath(id)
_.detect @activePackages, (pack) -> pack.path is path
getActivePackages: ->
_.clone(@activePackages)
activatePackageConfigs: ->
@activatePackageConfig(pack.path) for pack in @getLoadedPackages()
activatePackageConfig: (id, options) ->
if pack = @loadPackage(id, options)
@activePackages.push(pack)
pack.activateConfig()
pack
loadPackages: ->
@loadPackage(path) for path in @getAvailablePackagePaths() when not @isPackageDisabled(path)
loadPackage: (id, options) ->
if @isPackageDisabled(id)
return console.warn("Tried to load disabled packaged '#{id}'")
if path = @resolvePackagePath(id)
return pack if pack = @getLoadedPackage(id)
pack = Package.load(path, options)
@loadedPackages.push(pack)
pack
else
throw new Error("Could not resolve '#{id}' to a package path")
resolvePackagePath: _.memoize (id) ->
return id if fsUtils.isDirectory(id)
path = fsUtils.resolve(config.packageDirPaths..., id)
path if fsUtils.isDirectory(path)
getLoadedPackage: (id) ->
if path = @resolvePackagePath(id)
_.detect @loadedPackages, (pack) -> pack.path is path
isPackageLoaded: (id) ->
@getLoadedPackage(id)?
getLoadedPackages: ->
_.clone(@loadedPackages)
isPackageDisabled: (id) ->
if path = @resolvePackagePath(id)
_.include(config.get('core.disabledPackages') ? [], fsUtils.base(path))
getAvailablePackagePaths: ->
packagePaths = []
for packageDirPath in config.packageDirPaths
for packagePath in fsUtils.list(packageDirPath)
packagePaths.push(packagePath) if fsUtils.isDirectory(packagePath)
_.uniq(packagePaths)
getAvailablePackageNames: ->
fsUtils.base(path) for path in @getAvailablePackagePaths()
loadThemes: ->
themeNames = config.get("core.themes")
themeNames = [themeNames] unless _.isArray(themeNames)
@loadTheme(themeName) for themeName in themeNames
@loadUserStylesheet()
getAvailableThemePaths: ->
themePaths = []
for themeDirPath in config.themeDirPaths
themePaths.push(fsUtils.list(themeDirPath, ['', '.tmTheme', '.css', 'less'])...)
_.uniq(themePaths)
getAvailableThemeNames: ->
fsUtils.base(path).split('.')[0] for path in @getAvailableThemePaths()
loadTheme: (name) ->
@loadedThemes.push Theme.load(name)
loadUserStylesheet: ->
userStylesheetPath = fsUtils.resolve(fsUtils.join(config.configDirPath, 'user'), ['css', 'less'])
if fsUtils.isFile(userStylesheetPath)
userStyleesheetContents = loadStylesheet(userStylesheetPath)
applyStylesheet(userStylesheetPath, userStyleesheetContents, 'userTheme')
getAtomThemeStylesheets: ->
themeNames = config.get("core.themes") ? ['atom-dark-ui', 'atom-dark-syntax']
themeNames = [themeNames] unless _.isArray(themeNames)
open: (args...) ->
@sendMessageToBrowserProcess('open', args)
openDev: (args...) ->
@sendMessageToBrowserProcess('openDev', args)
newWindow: (args...) ->
@sendMessageToBrowserProcess('newWindow', args)
openConfig: ->
@sendMessageToBrowserProcess('openConfig')
restartRendererProcess: ->
@sendMessageToBrowserProcess('restartRendererProcess')
confirm: (message, detailedMessage, buttonLabelsAndCallbacks...) ->
wrapCallback = (callback) => => @dismissModal(callback)
@presentModal =>
args = [message, detailedMessage]
callbacks = []
while buttonLabelsAndCallbacks.length
do =>
buttonLabel = buttonLabelsAndCallbacks.shift()
buttonCallback = buttonLabelsAndCallbacks.shift()
args.push(buttonLabel)
callbacks.push(=> @dismissModal(buttonCallback))
@sendMessageToBrowserProcess('confirm', args, callbacks)
showSaveDialog: (callback) ->
@presentModal =>
@sendMessageToBrowserProcess('showSaveDialog', [], (path) => @dismissModal(callback, path))
presentModal: (fn) ->
if @presentingModal
@pushPendingModal(fn)
else
@presentingModal = true
fn()
dismissModal: (fn, args...) ->
@pendingModals.push([]) # prioritize any modals presented during dismiss callback
fn?(args...)
@presentingModal = false
if fn = @shiftPendingModal()
_.delay (=> @presentModal(fn)), 50 # let view update before next dialog
pushPendingModal: (fn) ->
# pendingModals is a stack of queues. enqueue to top of stack.
stackSize = @pendingModals.length
@pendingModals[stackSize - 1].push(fn)
shiftPendingModal: ->
# pop pendingModals stack if its top queue is empty, otherwise shift off the topmost queue
stackSize = @pendingModals.length
currentQueueSize = @pendingModals[stackSize - 1].length
if stackSize > 1 and currentQueueSize == 0
@pendingModals.pop()
@shiftPendingModal()
else
@pendingModals[stackSize - 1].shift()
toggleDevTools: ->
@sendMessageToBrowserProcess('toggleDevTools')
showDevTools: ->
@sendMessageToBrowserProcess('showDevTools')
focus: ->
@sendMessageToBrowserProcess('focus')
show: ->
@sendMessageToBrowserProcess('show')
exit: (status) ->
@sendMessageToBrowserProcess('exit', [status])
log: (message) ->
@sendMessageToBrowserProcess('log', [message])
beginTracing: ->
@sendMessageToBrowserProcess('beginTracing')
endTracing: ->
@sendMessageToBrowserProcess('endTracing')
toggleFullScreen: ->
@sendMessageToBrowserProcess('toggleFullScreen')
sendMessageToBrowserProcess: (name, data=[], callbacks) ->
messageId = messageIdCounter++
data.unshift(messageId)
callbacks = [callbacks] if typeof callbacks is 'function'
@pendingBrowserProcessCallbacks[messageId] = callbacks
originalSendMessageToBrowserProcess(name, data)
receiveMessageFromBrowserProcess: (name, data) ->
switch name
when 'reply'
[messageId, callbackIndex] = data.shift()
@pendingBrowserProcessCallbacks[messageId]?[callbackIndex]?(data...)
when 'openPath'
path = data[0]
rootView?.open(path)
setWindowState: (keyPath, value) ->
windowState = @getWindowState()
_.setValueForKeyPath(windowState, keyPath, value)
$native.setWindowState(JSON.stringify(windowState))
windowState
getWindowState: (keyPath) ->
windowState = JSON.parse(@getInMemoryWindowState() ? @getSavedWindowState() ? '{}')
if keyPath
_.valueForKeyPath(windowState, keyPath)
else
windowState
getInMemoryWindowState: ->
inMemoryState = $native.getWindowState()
if inMemoryState.length > 0
inMemoryState
else
null
getSavedWindowState: ->
storageKey = switch @windowMode
when 'editor' then window.location.params.pathToOpen
when 'config' then 'config'
localStorage[storageKey] if storageKey
saveWindowState: ->
storageKey = switch @windowMode
when 'editor' then @getPathToOpen()
when 'config' then 'config'
localStorage[storageKey] = JSON.stringify(@getWindowState())
update: ->
@sendMessageToBrowserProcess('update')
getUpdateStatus: (callback) ->
@sendMessageToBrowserProcess('getUpdateStatus', [], callback)
crashMainProcess: ->
@sendMessageToBrowserProcess('crash')
crashRenderProcess: ->
$native.crash()
requireUserInitScript: ->
userInitScriptPath = fsUtils.join(config.configDirPath, "user.coffee")
try
require userInitScriptPath if fsUtils.isFile(userInitScriptPath)
catch error
console.error "Failed to load `#{userInitScriptPath}`", error.stack, error
getVersion: (callback) ->
@sendMessageToBrowserProcess('getVersion', null, callback)