Files
atom/src/app/root-view.coffee
2012-11-19 09:30:21 -08:00

274 lines
8.1 KiB
CoffeeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
$ = require 'jquery'
{$$} = require 'space-pen'
fs = require 'fs'
_ = require 'underscore'
{View} = require 'space-pen'
Buffer = require 'buffer'
Editor = require 'editor'
Project = require 'project'
Pane = require 'pane'
PaneColumn = require 'pane-column'
PaneRow = require 'pane-row'
StatusBar = require 'status-bar'
TextMateTheme = require 'text-mate-theme'
module.exports =
class RootView extends View
@content: ->
@div id: 'root-view', tabindex: -1, =>
@div id: 'horizontal', outlet: 'horizontal', =>
@div id: 'vertical', outlet: 'vertical', =>
@div id: 'panes', outlet: 'panes'
@deserialize: ({ projectPath, panesViewState, extensionStates, fontSize }) ->
rootView = new RootView(projectPath, extensionStates: extensionStates, suppressOpen: true)
rootView.setRootPane(rootView.deserializeView(panesViewState)) if panesViewState
rootView.setFontSize(fontSize) if fontSize > 0
rootView
extensions: null
extensionStates: null
fontSize: 20
showInvisibles: false
invisibles: null
title: null
initialize: (pathToOpen, { @extensionStates, suppressOpen } = {}) ->
window.rootView = this
TextMateTheme.activate('IR_Black')
@invisibles =
eol: '¬'
space: ''
tab: ''
@extensionStates ?= {}
@extensions = {}
@project = new Project(pathToOpen)
@handleEvents()
@loadUserConfiguration()
if pathToOpen
@open(pathToOpen) if fs.isFile(pathToOpen) and not suppressOpen
else
@open()
serialize: ->
projectPath: @project?.getPath()
panesViewState: @panes.children().view()?.serialize()
extensionStates: @serializeExtensions()
fontSize: @getFontSize()
handleEvents: ->
@on 'toggle-dev-tools', => atom.toggleDevTools()
@on 'focus', (e) =>
if @getActiveEditor()
@getActiveEditor().focus()
false
else
@setTitle(null)
focusableChild = this.find("[tabindex=-1]:visible:first")
if focusableChild.length
focusableChild.focus()
false
else
true
@on 'active-editor-path-change', (e, path) =>
@project.setPath(path) unless @project.getRootDirectory()
if path
@setTitle(fs.base(path))
else
@setTitle("untitled")
@command 'window:increase-font-size', => @setFontSize(@getFontSize() + 1)
@command 'window:decrease-font-size', => @setFontSize(@getFontSize() - 1)
@command 'window:focus-next-pane', => @focusNextPane()
@command 'window:save-all', => @saveAll()
@command 'window:toggle-invisibles', => @setShowInvisibles(not @showInvisibles)
@command 'window:toggle-ignored-files', => @toggleIgnoredFiles()
afterAttach: (onDom) ->
@focus() if onDom
serializeExtensions: ->
extensionStates = {}
for name, extension of @extensions
try
extensionStates[name] = extension.serialize?()
catch e
console?.error("Exception serializing '#{name}' extension\n", e.stack)
extensionStates
deserializeView: (viewState) ->
switch viewState.viewClass
when 'Pane' then Pane.deserialize(viewState, this)
when 'PaneRow' then PaneRow.deserialize(viewState, this)
when 'PaneColumn' then PaneColumn.deserialize(viewState, this)
when 'Editor' then Editor.deserialize(viewState, this)
activateExtension: (extension, config) ->
throw new Error("Trying to activate an extension with no name attribute") unless extension.name?
@extensions[extension.name] = extension
extension.activate(this, @extensionStates[extension.name], config)
deactivateExtension: (extension) ->
extension.deactivate?()
delete @extensions[extension.name]
deactivate: ->
atom.setRootViewStateForPath(@project.getPath(), @serialize())
@deactivateExtension(extension) for name, extension of @extensions
@remove()
open: (path, options = {}) ->
changeFocus = options.changeFocus ? true
allowActiveEditorChange = options.allowActiveEditorChange ? false
unless editSession = @openInExistingEditor(path, allowActiveEditorChange, changeFocus)
editSession = @project.buildEditSessionForPath(path)
editor = new Editor({editSession, @showInvisibles})
pane = new Pane(editor)
@panes.append(pane)
if changeFocus
editor.focus()
else
@makeEditorActive(editor, changeFocus)
editSession
openInExistingEditor: (path, allowActiveEditorChange, changeFocus) ->
if activeEditor = @getActiveEditor()
activeEditor.focus() if changeFocus
path = @project.resolve(path) if path
if editSession = activeEditor.activateEditSessionForPath(path)
return editSession
if allowActiveEditorChange
for editor in @getEditors()
if editSession = editor.activateEditSessionForPath(path)
@makeEditorActive(editor, changeFocus)
return editSession
editSession = @project.buildEditSessionForPath(path)
activeEditor.edit(editSession)
editSession
editorFocused: (editor) ->
@makeEditorActive(editor) if @panes.containsElement(editor)
makeEditorActive: (editor, focus) ->
if focus
editor.focus()
return
previousActiveEditor = @panes.find('.editor.active').view()
previousActiveEditor?.removeClass('active').off('.root-view')
editor.addClass('active')
if not editor.mini
editor.on 'editor-path-change.root-view', =>
@trigger 'active-editor-path-change', editor.getPath()
if not previousActiveEditor or editor.getPath() != previousActiveEditor.getPath()
@trigger 'active-editor-path-change', editor.getPath()
activeKeybindings: ->
keymap.bindingsForElement(document.activeElement)
getTitle: ->
@title or "untitled"
setTitle: (title) ->
projectPath = @project.getPath()
if not projectPath
@title = "untitled"
else if title
@title = "#{title} #{projectPath}"
else
@title = projectPath
@updateWindowTitle()
updateWindowTitle: ->
document.title = @title
setShowInvisibles: (showInvisibles) ->
return if @showInvisibles == showInvisibles
@showInvisibles = showInvisibles
editor.setShowInvisibles(@showInvisibles) for editor in @getEditors()
toggleIgnoredFiles: ->
@project.toggleIgnoredFiles()
getEditors: ->
@panes.find('.pane > .editor').map(-> $(this).view()).toArray()
getModifiedBuffers: ->
modifiedBuffers = []
for editor in @getEditors()
for session in editor.editSessions
modifiedBuffers.push session.buffer if session.buffer.isModified()
modifiedBuffers
getOpenBufferPaths: ->
_.uniq(_.flatten(@getEditors().map (editor) -> editor.getOpenBufferPaths()))
getActiveEditor: ->
if (editor = @panes.find('.editor.active')).length
editor.view()
else
@panes.find('.editor:first').view()
getActiveEditSession: ->
@getActiveEditor()?.activeEditSession
focusNextPane: ->
panes = @panes.find('.pane')
currentIndex = panes.toArray().indexOf(@getFocusedPane()[0])
nextIndex = (currentIndex + 1) % panes.length
panes.eq(nextIndex).view().wrappedView.focus()
getFocusedPane: ->
@panes.find('.pane:has(:focus)')
setRootPane: (pane) ->
@panes.empty()
@panes.append(pane)
@adjustPaneDimensions()
adjustPaneDimensions: ->
rootPane = @panes.children().first().view()
rootPane?.css(width: '100%', height: '100%', top: 0, left: 0)
rootPane?.adjustDimensions()
remove: ->
editor.remove() for editor in @getEditors()
@project.destroy()
super
setFontSize: (newFontSize) ->
newFontSize = Math.max(1, newFontSize)
[oldFontSize, @fontSize] = [@fontSize, newFontSize]
@trigger 'font-size-change' if oldFontSize != newFontSize
getFontSize: -> @fontSize
setInvisibles: (invisibles={}) ->
_.extend(@invisibles, invisibles)
editor.setInvisibles(@invisibles) for editor in @getEditors()
getInvisibles: -> @invisibles
loadUserConfiguration: ->
try
require atom.configFilePath if fs.exists(atom.configFilePath)
catch error
console.error "Failed to load `#{atom.configFilePath}`", error.stack, error
saveAll: ->
editor.save() for editor in @getEditors()