Add WorkspaceElement

This commit is contained in:
Nathan Sobo
2014-09-24 19:42:36 -06:00
parent ae488fc7fe
commit 670f3e4946
7 changed files with 178 additions and 126 deletions

View File

@@ -3,7 +3,7 @@ Package = require '../src/package'
describe "PackageManager", ->
beforeEach ->
atom.workspaceView = new WorkspaceView
atom.workspaceView = atom.workspace.getView(atom.workspace).__spacePenView
describe "::loadPackage(name)", ->
it "continues if the package has an invalid package.json", ->

View File

@@ -26,10 +26,12 @@ describe "WorkspaceView", ->
simulateReload = ->
workspaceState = atom.workspace.serialize()
projectState = atom.project.serialize()
atom.workspaceView.debugId = 'initial'
atom.workspaceView.remove()
atom.project = atom.deserializers.deserialize(projectState)
atom.workspace = Workspace.deserialize(workspaceState)
atom.workspaceView = atom.workspace.getView(atom.workspace).__spacePenView
atom.workspaceView.debugId = 'second'
atom.workspaceView.attachToDom()
describe "when the serialized WorkspaceView has an unsaved buffer", ->

View File

@@ -208,6 +208,7 @@ class EditorView extends View
beforeRemove: ->
return unless @attached
@attached = false
debugger unless @component?.isMounted()
@unmountComponent()
@editor.destroy()
@trigger 'editor:detached', this

View File

@@ -1,6 +1,6 @@
{CompositeDisposable} = require 'event-kit'
{callAttachHooks} = require './space-pen-extensions'
PaneContainerView = require './pane-container-view'
PaneContainerView = null
_ = require 'underscore-plus'
module.exports =
@@ -8,6 +8,7 @@ class PaneContainerElement extends HTMLElement
createdCallback: ->
@subscriptions = new CompositeDisposable
@classList.add 'panes'
PaneContainerView ?= require './pane-container-view'
@__spacePenView = new PaneContainerView(this)
setModel: (@model) ->

View File

@@ -0,0 +1,153 @@
ipc = require 'ipc'
path = require 'path'
{Disposable, CompositeDisposable} = require 'event-kit'
Grim = require 'grim'
scrollbarStyle = require 'scrollbar-style'
{callAttachHooks} = require 'space-pen'
WorkspaceView = null
module.exports =
class WorkspaceElement extends HTMLElement
createdCallback: ->
@subscriptions = new CompositeDisposable
atom.commands.setRootNode(this)
@initializeContent()
@observeScrollbarStyle()
@observeTextEditorFontConfig()
@createSpacePenShim()
attachedCallback: ->
callAttachHooks(this)
@focus()
detachedCallback: ->
@model.destroy()
initializeContent: ->
@classList.add 'workspace'
@setAttribute 'tabindex', -1
@verticalAxis = document.createElement('div')
@verticalAxis.classList.add('vertical')
@horizontalAxis = document.createElement('div')
@horizontalAxis.classList.add('horizontal')
@horizontalAxis.appendChild(@verticalAxis)
@appendChild(@horizontalAxis)
observeScrollbarStyle: ->
@subscriptions.add scrollbarStyle.onValue (style) =>
switch style
when 'legacy'
@classList.remove('scrollbars-visible-when-scrolling')
@classList.add("scrollbars-visible-always")
when 'overlay'
@classList.remove('scrollbars-visible-always')
@classList.add("scrollbars-visible-when-scrolling")
observeTextEditorFontConfig: ->
@subscriptions.add atom.config.observe 'editor.fontSize', @setTextEditorFontSize
@subscriptions.add atom.config.observe 'editor.fontFamily', @setTextEditorFontFamily
@subscriptions.add atom.config.observe 'editor.lineHeight', @setTextEditorLineHeight
createSpacePenShim: ->
WorkspaceView ?= require './workspace-view'
@__spacePenView = new WorkspaceView(this)
getModel: -> @model
setModel: (@model) ->
@paneContainer = @model.getView(@model.paneContainer)
@verticalAxis.appendChild(@paneContainer)
@addEventListener 'focus', @handleFocus.bind(this)
handleWindowFocus = @handleWindowFocus.bind(this)
window.addEventListener 'focus', handleWindowFocus
@subscriptions.add(new Disposable => window.removeEventListener 'focus', handleWindowFocus)
@__spacePenView.setModel(@model)
# Essential: Focus the pane directly above the active pane.
focusPaneViewAbove: -> @panes.focusPaneViewAbove()
# Essential: Focus the pane directly below the active pane.
focusPaneViewBelow: -> @panes.focusPaneViewBelow()
# Essential: Focus the pane directly to the left of the active pane.
focusPaneViewOnLeft: -> @panes.focusPaneViewOnLeft()
# Essential: Focus the pane directly to the right of the active pane.
focusPaneViewOnRight: -> @panes.focusPaneViewOnRight()
###
Section: Private
###
setTextEditorFontSize: (fontSize) ->
atom.themes.updateGlobalEditorStyle('font-size', fontSize + 'px')
setTextEditorFontFamily: (fontFamily) ->
atom.themes.updateGlobalEditorStyle('font-family', fontFamily)
setTextEditorLineHeight: (lineHeight) ->
atom.themes.updateGlobalEditorStyle('line-height', lineHeight)
handleFocus: (event) ->
@model.getActivePane().activate()
handleWindowFocus: (event) ->
@handleFocus(event) if document.activeElement is document.body
if process.platform is 'darwin'
atom.commands.add '.workspace', 'window:install-shell-commands', -> @getModel().installShellCommands()
atom.commands.add '.workspace',
'window:increase-font-size': -> @getModel().increaseFontSize()
'window:decrease-font-size': -> @getModel().decreaseFontSize()
'window:reset-font-size': -> @getModel().resetFontSize()
'application:about': -> ipc.send('command', 'application:about')
'application:run-all-specs': -> ipc.send('command', 'application:run-all-specs')
'application:run-benchmarks': -> ipc.send('command', 'application:run-benchmarks')
'application:show-settings': -> ipc.send('command', 'application:show-settings')
'application:quit': -> ipc.send('command', 'application:quit')
'application:hide': -> ipc.send('command', 'application:hide')
'application:hide-other-applications': -> ipc.send('command', 'application:hide-other-applications')
'application:install-update': -> ipc.send('command', 'application:install-update')
'application:unhide-all-applications': -> ipc.send('command', 'application:unhide-all-applications')
'application:new-window': -> ipc.send('command', 'application:new-window')
'application:new-file': -> ipc.send('command', 'application:new-file')
'application:open': -> ipc.send('command', 'application:open')
'application:open-file': -> ipc.send('command', 'application:open-file')
'application:open-folder': -> ipc.send('command', 'application:open-folder')
'application:open-dev': -> ipc.send('command', 'application:open-dev')
'application:open-safe': -> ipc.send('command', 'application:open-safe')
'application:minimize': -> ipc.send('command', 'application:minimize')
'application:zoom': -> ipc.send('command', 'application:zoom')
'application:bring-all-windows-to-front': -> ipc.send('command', 'application:bring-all-windows-to-front')
'application:open-your-config': -> ipc.send('command', 'application:open-your-config')
'application:open-your-init-script': -> ipc.send('command', 'application:open-your-init-script')
'application:open-your-keymap': -> ipc.send('command', 'application:open-your-keymap')
'application:open-your-snippets': -> ipc.send('command', 'application:open-your-snippets')
'application:open-your-stylesheet': -> ipc.send('command', 'application:open-your-stylesheet')
'application:open-license': -> @getModel().openLicense()
'window:run-package-specs': -> ipc.send('run-package-specs', path.join(atom.project.getPath(), 'spec'))
'window:focus-next-pane': -> @getModel().activateNextPane()
'window:focus-previous-pane': -> @getModel().activatePreviousPane()
'window:focus-pane-above': -> @focusPaneViewAbove()
'window:focus-pane-below': -> @focusPaneViewBelow()
'window:focus-pane-on-left': -> @focusPaneViewOnLeft()
'window:focus-pane-on-right': -> @focusPaneViewOnRight()
'window:save-all': -> @getModel().saveAll()
'window:toggle-invisibles': -> atom.config.toggle("editor.showInvisibles")
'window:log-deprecation-warnings': -> Grim.logDeprecationWarnings()
'window:toggle-auto-indent': -> atom.config.toggle("editor.autoIndent")
'pane:reopen-closed-item': -> @getModel().reopenItem()
'core:close': -> @getModel().destroyActivePaneItemOrEmptyPane()
'core:save': -> @getModel().saveActivePaneItem()
'core:save-as': -> @getModel().saveActivePaneItemAs()
module.exports = WorkspaceElement = document.registerElement 'atom-workspace',
prototype: WorkspaceElement.prototype
extends: 'div'

View File

@@ -7,16 +7,10 @@ Delegator = require 'delegato'
scrollbarStyle = require 'scrollbar-style'
{$, $$, View} = require './space-pen-extensions'
fs = require 'fs-plus'
Workspace = require './workspace'
PaneView = require './pane-view'
PaneContainerView = require './pane-container-view'
Editor = require './editor'
atom.commands.add '.workspace',
'window:increase-font-size': -> @getModel().increaseFontSize()
'window:decrease-font-size': -> @getModel().decreaseFontSize()
'window:reset-font-size': -> @getModel().resetFontSize()
# Extended: The top-level view for the entire window. An instance of this class is
# available via the `atom.workspaceView` global.
#
@@ -62,8 +56,6 @@ class WorkspaceView extends View
'saveActivePaneItem', 'saveActivePaneItemAs', 'saveAll', 'destroyActivePaneItem',
'destroyActivePane', 'increaseFontSize', 'decreaseFontSize', toProperty: 'model'
@version: 4
@configDefaults:
ignoredNames: [".git", ".hg", ".svn", ".DS_Store", "Thumbs.db"]
excludeVcsIgnoredPaths: true
@@ -73,91 +65,18 @@ class WorkspaceView extends View
audioBeep: true
destroyEmptyPanes: true
@content: ->
@div class: 'workspace', tabindex: -1, =>
@div class: 'horizontal', outlet: 'horizontal', =>
@div class: 'vertical', outlet: 'vertical', =>
@div class: 'panes', outlet: 'panes'
initialize: (model) ->
@model = model ? atom.workspace ? new Workspace unless @model?
@element.getModel = -> model
atom.commands.setRootNode(@[0])
panes = @model.getView(@model.paneContainer).__spacePenView
@panes.replaceWith(panes)
@panes = panes
constructor: (@element) ->
super
@deprecatedViewEvents()
setModel: (@model) ->
@horizontal = @find('.horizontal')
@vertical = @find('.vertical')
@panes = @find('.panes').view()
@subscribe @model.onDidOpen => @trigger 'uri-opened'
@subscribe scrollbarStyle, (style) =>
@removeClass('scrollbars-visible-always scrollbars-visible-when-scrolling')
switch style
when 'legacy'
@addClass("scrollbars-visible-always")
when 'overlay'
@addClass("scrollbars-visible-when-scrolling")
@subscribe atom.config.observe 'editor.fontSize', @setEditorFontSize
@subscribe atom.config.observe 'editor.fontFamily', @setEditorFontFamily
@subscribe atom.config.observe 'editor.lineHeight', @setEditorLineHeight
@on 'focus', (e) => @handleFocus(e)
@subscribe $(window), 'focus', (e) =>
@handleFocus(e) if document.activeElement is document.body
@command 'application:about', -> ipc.send('command', 'application:about')
@command 'application:run-all-specs', -> ipc.send('command', 'application:run-all-specs')
@command 'application:run-benchmarks', -> ipc.send('command', 'application:run-benchmarks')
@command 'application:show-settings', -> ipc.send('command', 'application:show-settings')
@command 'application:quit', -> ipc.send('command', 'application:quit')
@command 'application:hide', -> ipc.send('command', 'application:hide')
@command 'application:hide-other-applications', -> ipc.send('command', 'application:hide-other-applications')
@command 'application:install-update', -> ipc.send('command', 'application:install-update')
@command 'application:unhide-all-applications', -> ipc.send('command', 'application:unhide-all-applications')
@command 'application:new-window', -> ipc.send('command', 'application:new-window')
@command 'application:new-file', -> ipc.send('command', 'application:new-file')
@command 'application:open', -> ipc.send('command', 'application:open')
@command 'application:open-file', -> ipc.send('command', 'application:open-file')
@command 'application:open-folder', -> ipc.send('command', 'application:open-folder')
@command 'application:open-dev', -> ipc.send('command', 'application:open-dev')
@command 'application:open-safe', -> ipc.send('command', 'application:open-safe')
@command 'application:minimize', -> ipc.send('command', 'application:minimize')
@command 'application:zoom', -> ipc.send('command', 'application:zoom')
@command 'application:bring-all-windows-to-front', -> ipc.send('command', 'application:bring-all-windows-to-front')
@command 'application:open-your-config', -> ipc.send('command', 'application:open-your-config')
@command 'application:open-your-init-script', -> ipc.send('command', 'application:open-your-init-script')
@command 'application:open-your-keymap', -> ipc.send('command', 'application:open-your-keymap')
@command 'application:open-your-snippets', -> ipc.send('command', 'application:open-your-snippets')
@command 'application:open-your-stylesheet', -> ipc.send('command', 'application:open-your-stylesheet')
@command 'application:open-license', => @model.openLicense()
if process.platform is 'darwin'
@command 'window:install-shell-commands', => @getModel().installShellCommands()
@command 'window:run-package-specs', -> ipc.send('run-package-specs', path.join(atom.project.getPath(), 'spec'))
@command 'window:focus-next-pane', => @focusNextPaneView()
@command 'window:focus-previous-pane', => @focusPreviousPaneView()
@command 'window:focus-pane-above', => @focusPaneViewAbove()
@command 'window:focus-pane-below', => @focusPaneViewBelow()
@command 'window:focus-pane-on-left', => @focusPaneViewOnLeft()
@command 'window:focus-pane-on-right', => @focusPaneViewOnRight()
@command 'window:save-all', => @saveAll()
@command 'window:toggle-invisibles', -> atom.config.toggle("editor.showInvisibles")
@command 'window:log-deprecation-warnings', -> logDeprecationWarnings()
@command 'window:toggle-auto-indent', ->
atom.config.toggle("editor.autoIndent")
@command 'pane:reopen-closed-item', => @getModel().reopenItem()
@command 'core:close', => if @getModel().getActivePaneItem()? then @destroyActivePaneItem() else @destroyActivePane()
@command 'core:save', => @saveActivePaneItem()
@command 'core:save-as', => @saveActivePaneItemAs()
@deprecatedViewEvents()
beforeRemove: ->
@model?.destroy()
###
Section: Accessing the Workspace Model
@@ -309,35 +228,6 @@ class WorkspaceView extends View
Section: Private
###
afterAttach: (onDom) ->
@focus() if onDom
# Called by SpacePen
beforeRemove: ->
@model.destroy()
setEditorFontSize: (fontSize) ->
atom.themes.updateGlobalEditorStyle('font-size', fontSize + 'px')
setEditorFontFamily: (fontFamily) ->
atom.themes.updateGlobalEditorStyle('font-family', fontFamily)
setEditorLineHeight: (lineHeight) ->
atom.themes.updateGlobalEditorStyle('line-height', lineHeight)
handleFocus: ->
if @getActivePaneView()
@getActivePaneView().focus()
false
else
focusableChild = @find("[tabindex=-1]:visible:first")
if focusableChild.length
focusableChild.focus()
false
else
$(document.body).focus()
true
# Prompts to save all unsaved items
confirmClose: ->
@model.confirmClose()

View File

@@ -11,7 +11,7 @@ Editor = require './editor'
PaneContainer = require './pane-container'
Pane = require './pane'
ViewRegistry = require './view-registry'
WorkspaceView = null
WorkspaceElement = require './workspace-element'
# Essential: Represents the state of the user interface for the entire window.
# An instance of this class is available via the `atom.workspace` global.
@@ -58,6 +58,10 @@ class Workspace extends Model
when 'atom://.atom/init-script'
@open(atom.getUserInitScriptPath())
@addViewProvider
modelConstructor: Workspace
viewConstructor: WorkspaceElement
# Called by the Serializable mixin during deserialization
deserializeParams: (params) ->
for packageName in params.packagesWithActiveGrammars ? []
@@ -74,9 +78,6 @@ class Workspace extends Model
fullScreen: atom.isFullScreen()
packagesWithActiveGrammars: @getPackageNamesWithActiveGrammars()
getViewClass: ->
WorkspaceView ?= require './workspace-view'
getPackageNamesWithActiveGrammars: ->
packageNames = []
addGrammar = ({includedGrammarScopes, packageName}={}) ->
@@ -152,7 +153,7 @@ class Workspace extends Model
# Updates the application's title and proxy icon based on whichever file is
# open.
updateWindowTitle: =>
if projectPath = atom.project.getPath()
if projectPath = atom.project?.getPath()
if item = @getActivePaneItem()
document.title = "#{item.getTitle?() ? 'untitled'} - #{projectPath}"
atom.setRepresentedFilename(item.getPath?())
@@ -556,6 +557,10 @@ class Workspace extends Model
destroyActivePane: ->
@activePane?.destroy()
# Destroy the active pane item or the active pane if it is empty.
destroyActivePaneItemOrEmptyPane: ->
if @getActivePaneItem()? then @destroyActivePaneItem() else @destroyActivePane()
# Increase the editor font size by 1px.
increaseFontSize: ->
atom.config.set("editor.fontSize", atom.config.get("editor.fontSize") + 1)