Comparar commits

...

10 Commits

Autor SHA1 Mensagem Data
Nathan Sobo 7e59be6461 Use atom.views.getView in WorkspaceView to preserve previous behavior
The status-bar package specs were calling atom.views.getView with the
workspace model *prior* to instantiating the SpacePen view. A weird
case, but might as well leave it working so the deprecation shim is
perfect.
2014-11-30 18:43:50 -07:00
Nathan Sobo 81422d71cb 📝 Publicize and document WorkspaceElement 2014-11-30 18:33:22 -07:00
Nathan Sobo fa242dca7a 📝 Update ViewFactory API docs 2014-11-30 18:21:31 -07:00
Nathan Sobo 2ac15bad90 Return views created via atom.views.createView from atom.views.getView
The .getView method is deprecated, but this is required to maintain the
spirit of the old behavior for now.
2014-11-30 18:06:06 -07:00
Nathan Sobo 1e6e724be7 Deprecate atom.views.getView and store view registry on WorkspaceElement
This separates the role of the ViewFactory from the ViewRegistry.
The ViewFactory creates *new* views. The ViewRegistry maintains a
persistent 1:1 mapping from models to views, and is owned by the
workspace rather than being a global service. If someone wants to 
*create* a view, they use atom.views.createView. If someone wants to
get the workspace’s view element for a given model, they call .getView
on the workspace.
2014-11-30 17:12:35 -07:00
Nathan Sobo 05e7e9fc1d Rename ViewRegistry to ViewFactory
The new ViewRegistry will be focused only on storing model::view
associations, leaving the global factory to focus on creating them.
2014-11-30 15:49:49 -07:00
Nathan Sobo 80c354aad4 💄 2014-11-30 15:44:26 -07:00
Nathan Sobo aa5c09cf0b Log a deprecation warning when models still implement .getViewClass 2014-11-30 15:43:33 -07:00
Nathan Sobo d79ca646a8 Allow params to be passed to ViewRegistry::createView
Now we call initialize on the created view instead of setModel, which
emphasizes the fact that it’s only called once and allows arbitrary
properties to be passed through during creation.
2014-11-30 15:42:14 -07:00
Nathan Sobo d8137cfcad Remove view registry references from the workspace model layer
Removed various ::getView methods from the model. Using the atom.views
global in the views for now, but going to switch them over to using a
locally assigned view registry instead in a subsequent commit.
2014-11-30 14:47:51 -07:00
38 arquivos alterados com 387 adições e 381 exclusões
+1 -1
Ver Arquivo
@@ -9,7 +9,7 @@ describe "editorView.", ->
beforeEach ->
atom.workspaceViewParentSelector = '#jasmine-content'
atom.workspaceView = atom.views.getView(atom.workspace).__spacePenView
atom.workspaceView = atom.views.createView(atom.workspace).__spacePenView
atom.workspaceView.attachToDom()
atom.workspaceView.width(1024)
+2 -1
Ver Arquivo
@@ -33,7 +33,8 @@ unless process.env.ATOM_SHELL_INTERNAL_RUN_AS_NODE
Object.defineProperty module.exports, 'WorkspaceView', get: ->
deprecate """
Requiring `WorkspaceView` from `atom` is no longer supported.
Use `atom.views.getView(atom.workspace)` instead.
Use `document.querySelector('atom-workspace')` if you need to access
the workspace element.
"""
require '../src/workspace-view'
@@ -9,6 +9,6 @@ module.exports =
atom.commands.add 'atom-workspace', 'activation-command', =>
@activationCommandCallCount++
editorView = atom.views.getView(atom.workspace.getActiveEditor())?.__spacePenView
editorView = document.querySelector('atom-workspace').getView(atom.workspace.getActiveEditor())?.__spacePenView
editorView?.command 'activation-command', =>
@legacyActivationCommandCallCount++
+2 -2
Ver Arquivo
@@ -4,7 +4,7 @@ Package = require '../src/package'
describe "PackageManager", ->
workspaceElement = null
beforeEach ->
workspaceElement = atom.views.getView(atom.workspace)
workspaceElement = atom.views.createView(atom.workspace)
describe "::loadPackage(name)", ->
it "continues if the package has an invalid package.json", ->
@@ -144,7 +144,7 @@ describe "PackageManager", ->
atom.workspace.open()
runs ->
editorView = atom.views.getView(atom.workspace.getActiveEditor()).__spacePenView
editorView = workspaceElement.getView(atom.workspace.getActiveEditor()).__spacePenView
legacyCommandListener = jasmine.createSpy("legacyCommandListener")
editorView.command 'activation-command', legacyCommandListener
editorCommandListener = jasmine.createSpy("editorCommandListener")
+9 -7
Ver Arquivo
@@ -5,9 +5,10 @@ PaneContainerView = require '../src/pane-container-view'
PaneView = require '../src/pane-view'
{Disposable} = require 'event-kit'
{$, View, $$} = require '../src/space-pen-extensions'
ViewRegistry = require '../src/view-registry'
describe "PaneContainerView", ->
[TestView, container, pane1, pane2, pane3, deserializerDisposable] = []
[viewRegistry, TestView, container, pane1, pane2, pane3, deserializerDisposable] = []
beforeEach ->
class TestView extends View
@@ -22,7 +23,8 @@ describe "PaneContainerView", ->
onDidChangeTitle: -> new Disposable(->)
onDidChangeModified: -> new Disposable(->)
container = atom.views.getView(atom.workspace.paneContainer).__spacePenView
viewRegistry = new ViewRegistry(atom.views)
container = atom.views.createView(atom.workspace.paneContainer, {viewRegistry}).__spacePenView
pane1 = container.getRoot()
pane1.activateItem(new TestView('1'))
pane2 = pane1.splitRight(new TestView('2'))
@@ -76,7 +78,7 @@ describe "PaneContainerView", ->
describe "serialization", ->
it "can be serialized and deserialized, and correctly adjusts dimensions of deserialized panes after attach", ->
newContainer = atom.views.getView(container.model.testSerialization()).__spacePenView
newContainer = atom.views.createView(container.model.testSerialization(), {viewRegistry}).__spacePenView
expect(newContainer.find('atom-pane-axis.horizontal > :contains(1)')).toExist()
expect(newContainer.find('atom-pane-axis.horizontal > atom-pane-axis.vertical > :contains(2)')).toExist()
expect(newContainer.find('atom-pane-axis.horizontal > atom-pane-axis.vertical > :contains(3)')).toExist()
@@ -92,14 +94,14 @@ describe "PaneContainerView", ->
describe "if the 'core.destroyEmptyPanes' config option is false (the default)", ->
it "leaves the empty panes intact", ->
newContainer = atom.views.getView(container.model.testSerialization()).__spacePenView
newContainer = atom.views.createView(container.model.testSerialization(), {viewRegistry}).__spacePenView
expect(newContainer.find('atom-pane-axis.horizontal > :contains(1)')).toExist()
expect(newContainer.find('atom-pane-axis.horizontal > atom-pane-axis.vertical > atom-pane').length).toBe 2
describe "if the 'core.destroyEmptyPanes' config option is true", ->
it "removes empty panes on deserialization", ->
atom.config.set('core.destroyEmptyPanes', true)
newContainer = atom.views.getView(container.model.testSerialization()).__spacePenView
newContainer = atom.views.createView(container.model.testSerialization(), {viewRegistry}).__spacePenView
expect(newContainer.find('atom-pane-axis.horizontal, atom-pane-axis.vertical')).not.toExist()
expect(newContainer.find('> :contains(1)')).toExist()
@@ -112,7 +114,7 @@ describe "PaneContainerView", ->
item2b = new TestView('2b')
item3a = new TestView('3a')
container = atom.views.getView(new PaneContainer).__spacePenView
container = atom.views.createView(new PaneContainer, {viewRegistry}).__spacePenView
pane1 = container.getRoot()
pane1.activateItem(item1a)
container.attachToDom()
@@ -262,7 +264,7 @@ describe "PaneContainerView", ->
# |7|8|9|
# -------
container = atom.views.getView(new PaneContainer).__spacePenView
container = atom.views.createView(new PaneContainer, {viewRegistry}).__spacePenView
pane1 = container.getRoot()
pane1.activateItem(new TestView('1'))
pane4 = pane1.splitDown(new TestView('4'))
+10 -8
Ver Arquivo
@@ -1,5 +1,6 @@
PaneContainer = require '../src/pane-container'
PaneView = require '../src/pane-view'
ViewRegistry = require '../src/view-registry'
fs = require 'fs-plus'
{Emitter, Disposable} = require 'event-kit'
{$, View} = require '../src/space-pen-extensions'
@@ -7,7 +8,7 @@ path = require 'path'
temp = require 'temp'
describe "PaneView", ->
[container, containerModel, view1, view2, editor1, editor2, pane, paneModel, deserializerDisposable] = []
[viewRegistry, container, containerModel, view1, view2, editor1, editor2, pane, paneModel, deserializerDisposable] = []
class TestView extends View
@deserialize: ({id, text}) -> new TestView({id, text})
@@ -27,7 +28,8 @@ describe "PaneView", ->
jasmine.snapshotDeprecations()
deserializerDisposable = atom.deserializers.add(TestView)
container = atom.views.getView(new PaneContainer).__spacePenView
viewRegistry = new ViewRegistry(atom.views)
container = atom.views.createView(new PaneContainer, {viewRegistry}).__spacePenView
containerModel = container.model
view1 = new TestView(id: 'view-1', text: 'View 1')
view2 = new TestView(id: 'view-2', text: 'View 2')
@@ -229,7 +231,7 @@ describe "PaneView", ->
beforeEach ->
pane2Model = paneModel.splitRight() # Can't destroy the last pane, so we add another
pane2 = containerModel.getView(pane2Model).__spacePenView
pane2 = viewRegistry.getView(pane2Model).__spacePenView
it "triggers a 'pane:removed' event with the pane", ->
removedHandler = jasmine.createSpy("removedHandler")
@@ -262,7 +264,7 @@ describe "PaneView", ->
beforeEach ->
pane2Model = paneModel.splitRight(items: [pane.copyActiveItem()])
pane2 = containerModel.getView(pane2Model).__spacePenView
pane2 = viewRegistry.getView(pane2Model).__spacePenView
expect(pane2Model.isActive()).toBe true
it "adds or removes the .active class as appropriate", ->
@@ -309,8 +311,8 @@ describe "PaneView", ->
pane2Model = pane1Model.splitRight(items: [pane1Model.copyActiveItem()])
pane3Model = pane2Model.splitDown(items: [pane2Model.copyActiveItem()])
pane2 = pane2Model._view
pane2 = containerModel.getView(pane2Model).__spacePenView
pane3 = containerModel.getView(pane3Model).__spacePenView
pane2 = viewRegistry.getView(pane2Model).__spacePenView
pane3 = viewRegistry.getView(pane3Model).__spacePenView
expect(container.find('> atom-pane-axis.horizontal > atom-pane').toArray()).toEqual [pane1[0]]
expect(container.find('> atom-pane-axis.horizontal > atom-pane-axis.vertical > atom-pane').toArray()).toEqual [pane2[0], pane3[0]]
@@ -323,13 +325,13 @@ describe "PaneView", ->
container.attachToDom()
pane.focus()
container2 = atom.views.getView(container.model.testSerialization()).__spacePenView
container2 = viewRegistry.getView(container.model.testSerialization()).__spacePenView
pane2 = container2.getRoot()
container2.attachToDom()
expect(pane2).toMatchSelector(':has(:focus)')
$(document.activeElement).blur()
container3 = atom.views.getView(container.model.testSerialization()).__spacePenView
container3 = viewRegistry.getView(container.model.testSerialization()).__spacePenView
pane3 = container3.getRoot()
container3.attachToDom()
expect(pane3).not.toMatchSelector(':has(:focus)')
+36 -35
Ver Arquivo
@@ -1,8 +1,8 @@
ViewRegistry = require '../src/view-registry'
Panel = require '../src/panel'
PanelElement = require '../src/panel-element'
PanelContainer = require '../src/panel-container'
PanelContainerElement = require '../src/panel-container-element'
ViewRegistry = require '../src/view-registry'
describe "PanelContainerElement", ->
[jasmineContent, element, container, viewRegistry] = []
@@ -13,25 +13,26 @@ describe "PanelContainerElement", ->
class TestPanelContainerItemElement extends HTMLElement
createdCallback: ->
@classList.add('test-root')
setModel: (@model) ->
initialize: ({@model}) ->
TestPanelContainerItemElement = document.registerElement 'atom-test-container-item-element', prototype: TestPanelContainerItemElement.prototype
beforeEach ->
jasmineContent = document.body.querySelector('#jasmine-content')
viewRegistry = new ViewRegistry
viewRegistry.addViewProvider
atom.views.addViewProvider
modelConstructor: Panel
viewConstructor: PanelElement
viewRegistry.addViewProvider
atom.views.addViewProvider
modelConstructor: PanelContainer
viewConstructor: PanelContainerElement
viewRegistry.addViewProvider
atom.views.addViewProvider
modelConstructor: TestPanelContainerItem
viewConstructor: TestPanelContainerItemElement
container = new PanelContainer({viewRegistry, location: 'left'})
element = container.getView()
container = new PanelContainer({location: 'left'})
viewRegistry = new ViewRegistry(atom.views)
element = viewRegistry.getView(container, {viewRegistry})
jasmineContent.appendChild(element)
it 'has a location class with value from the model', ->
@@ -44,9 +45,9 @@ describe "PanelContainerElement", ->
describe "adding and removing panels", ->
it "allows panels to be inserted at any position", ->
panel1 = new Panel({viewRegistry, item: new TestPanelContainerItem(), priority: 10})
panel2 = new Panel({viewRegistry, item: new TestPanelContainerItem(), priority: 5})
panel3 = new Panel({viewRegistry, item: new TestPanelContainerItem(), priority: 8})
panel1 = new Panel({item: new TestPanelContainerItem(), priority: 10})
panel2 = new Panel({item: new TestPanelContainerItem(), priority: 5})
panel3 = new Panel({item: new TestPanelContainerItem(), priority: 8})
container.addPanel(panel1)
container.addPanel(panel2)
@@ -60,7 +61,7 @@ describe "PanelContainerElement", ->
it "adds atom-panel elements when a new panel is added to the container; removes them when the panels are destroyed", ->
expect(element.childNodes.length).toBe 0
panel1 = new Panel({viewRegistry, item: new TestPanelContainerItem()})
panel1 = new Panel({item: new TestPanelContainerItem()})
container.addPanel(panel1)
expect(element.childNodes.length).toBe 1
expect(element.childNodes[0]).toHaveClass 'left'
@@ -69,12 +70,12 @@ describe "PanelContainerElement", ->
expect(element.childNodes[0].tagName).toBe 'ATOM-PANEL'
panel2 = new Panel({viewRegistry, item: new TestPanelContainerItem()})
panel2 = new Panel({item: new TestPanelContainerItem()})
container.addPanel(panel2)
expect(element.childNodes.length).toBe 2
expect(panel1.getView().style.display).not.toBe 'none'
expect(panel2.getView().style.display).not.toBe 'none'
expect(viewRegistry.getView(panel1).style.display).not.toBe 'none'
expect(viewRegistry.getView(panel2).style.display).not.toBe 'none'
panel1.destroy()
expect(element.childNodes.length).toBe 1
@@ -84,26 +85,26 @@ describe "PanelContainerElement", ->
describe "when the container is at the bottom location", ->
beforeEach ->
container = new PanelContainer({viewRegistry, location: 'bottom'})
element = container.getView()
container = new PanelContainer({location: 'bottom'})
element = viewRegistry.getView(container)
jasmineContent.appendChild(element)
it "adds atom-panel elements when a new panel is added to the container; removes them when the panels are destroyed", ->
expect(element.childNodes.length).toBe 0
panel1 = new Panel({viewRegistry, item: new TestPanelContainerItem(), className: 'one'})
panel1 = new Panel({item: new TestPanelContainerItem(), className: 'one'})
container.addPanel(panel1)
expect(element.childNodes.length).toBe 1
expect(element.childNodes[0]).toHaveClass 'bottom'
expect(element.childNodes[0]).toHaveClass 'tool-panel' # legacy selector support
expect(element.childNodes[0]).toHaveClass 'panel-bottom' # legacy selector support
expect(element.childNodes[0].tagName).toBe 'ATOM-PANEL'
expect(panel1.getView()).toHaveClass 'one'
expect(viewRegistry.getView(panel1)).toHaveClass 'one'
panel2 = new Panel({viewRegistry, item: new TestPanelContainerItem(), className: 'two'})
panel2 = new Panel({item: new TestPanelContainerItem(), className: 'two'})
container.addPanel(panel2)
expect(element.childNodes.length).toBe 2
expect(panel2.getView()).toHaveClass 'two'
expect(viewRegistry.getView(panel2)).toHaveClass 'two'
panel1.destroy()
expect(element.childNodes.length).toBe 1
@@ -113,34 +114,34 @@ describe "PanelContainerElement", ->
describe "when the container is modal", ->
beforeEach ->
container = new PanelContainer({viewRegistry, location: 'modal'})
element = container.getView()
container = new PanelContainer({location: 'modal'})
element = viewRegistry.getView(container)
jasmineContent.appendChild(element)
it "allows only one panel to be visible at a time", ->
panel1 = new Panel({viewRegistry, item: new TestPanelContainerItem()})
panel1 = new Panel({item: new TestPanelContainerItem()})
container.addPanel(panel1)
expect(panel1.getView().style.display).not.toBe 'none'
expect(viewRegistry.getView(panel1).style.display).not.toBe 'none'
panel2 = new Panel({viewRegistry, item: new TestPanelContainerItem()})
panel2 = new Panel({item: new TestPanelContainerItem()})
container.addPanel(panel2)
expect(panel1.getView().style.display).toBe 'none'
expect(panel2.getView().style.display).not.toBe 'none'
expect(viewRegistry.getView(panel1).style.display).toBe 'none'
expect(viewRegistry.getView(panel2).style.display).not.toBe 'none'
panel1.show()
expect(panel1.getView().style.display).not.toBe 'none'
expect(panel2.getView().style.display).toBe 'none'
expect(viewRegistry.getView(panel1).style.display).not.toBe 'none'
expect(viewRegistry.getView(panel2).style.display).toBe 'none'
it "adds the 'modal' class to panels", ->
panel1 = new Panel({viewRegistry, item: new TestPanelContainerItem()})
panel1 = new Panel({item: new TestPanelContainerItem()})
container.addPanel(panel1)
expect(panel1.getView()).toHaveClass 'modal'
expect(viewRegistry.getView(panel1)).toHaveClass 'modal'
# legacy selector support
expect(panel1.getView()).not.toHaveClass 'tool-panel'
expect(panel1.getView()).toHaveClass 'overlay'
expect(panel1.getView()).toHaveClass 'from-top'
expect(viewRegistry.getView(panel1)).not.toHaveClass 'tool-panel'
expect(viewRegistry.getView(panel1)).toHaveClass 'overlay'
expect(viewRegistry.getView(panel1)).toHaveClass 'from-top'
+4 -6
Ver Arquivo
@@ -1,16 +1,14 @@
ViewRegistry = require '../src/view-registry'
Panel = require '../src/panel'
PanelContainer = require '../src/panel-container'
describe "PanelContainer", ->
[container, viewRegistry] = []
[container] = []
class TestPanelItem
constructior: ->
beforeEach ->
viewRegistry = new ViewRegistry
container = new PanelContainer({viewRegistry})
container = new PanelContainer
describe "::addPanel(panel)", ->
it 'emits an onDidAddPanel event with the index the panel was inserted at', ->
@@ -46,7 +44,7 @@ describe "PanelContainer", ->
[initialPanel] = []
beforeEach ->
# 'left' logic is the same as 'top'
container = new PanelContainer({viewRegistry, location: 'left'})
container = new PanelContainer({location: 'left'})
initialPanel = new Panel(item: new TestPanelItem())
container.addPanel(initialPanel)
@@ -75,7 +73,7 @@ describe "PanelContainer", ->
[initialPanel] = []
beforeEach ->
# 'bottom' logic is the same as 'right'
container = new PanelContainer({viewRegistry, location: 'right'})
container = new PanelContainer({location: 'right'})
initialPanel = new Panel(item: new TestPanelItem())
container.addPanel(initialPanel)
+20 -13
Ver Arquivo
@@ -1,6 +1,6 @@
ViewRegistry = require '../src/view-registry'
Panel = require '../src/panel'
PanelElement = require '../src/panel-element'
ViewRegistry = require '../src/view-registry'
describe "PanelElement", ->
[jasmineContent, element, panel, viewRegistry] = []
@@ -11,23 +11,30 @@ describe "PanelElement", ->
class TestPanelItemElement extends HTMLElement
createdCallback: ->
@classList.add('test-root')
setModel: (@model) ->
initialize: ({@model}) ->
TestPanelItemElement = document.registerElement 'atom-test-item-element', prototype: TestPanelItemElement.prototype
beforeEach ->
jasmineContent = document.body.querySelector('#jasmine-content')
viewRegistry = new ViewRegistry
viewRegistry.addViewProvider
atom.views.addViewProvider
modelConstructor: Panel
viewConstructor: PanelElement
viewRegistry.addViewProvider
atom.views.addViewProvider
modelConstructor: TestPanelItem
viewConstructor: TestPanelItemElement
viewRegistry = new ViewRegistry(atom.views)
it "renders a view for the panel's item", ->
panel = new Panel({item: new TestPanelItem})
element = atom.views.createView(panel, {viewRegistry})
jasmineContent.appendChild(element)
expect(element.firstChild).toBe viewRegistry.getView(panel.getItem())
it 'removes the element when the panel is destroyed', ->
panel = new Panel({viewRegistry, item: new TestPanelItem})
element = panel.getView()
panel = new Panel({item: new TestPanelItem})
element = atom.views.createView(panel, {viewRegistry})
jasmineContent.appendChild(element)
expect(element.parentNode).toBe jasmineContent
@@ -36,15 +43,15 @@ describe "PanelElement", ->
describe "changing panel visibility", ->
it 'initially renders panel created with visibile: false', ->
panel = new Panel({viewRegistry, visible: false, item: new TestPanelItem})
element = panel.getView()
panel = new Panel({visible: false, item: new TestPanelItem})
element = atom.views.createView(panel, {viewRegistry})
jasmineContent.appendChild(element)
expect(element.style.display).toBe 'none'
it 'hides and shows the panel element when Panel::hide() and Panel::show() are called', ->
panel = new Panel({viewRegistry, item: new TestPanelItem})
element = panel.getView()
panel = new Panel({item: new TestPanelItem})
element = atom.views.createView(panel, {viewRegistry})
jasmineContent.appendChild(element)
expect(element.style.display).not.toBe 'none'
@@ -57,8 +64,8 @@ describe "PanelElement", ->
describe "when a class name is specified", ->
it 'initially renders panel created with visibile: false', ->
panel = new Panel({viewRegistry, className: 'some classes', item: new TestPanelItem})
element = panel.getView()
panel = new Panel({className: 'some classes', item: new TestPanelItem})
element = atom.views.createView(panel, {viewRegistry})
jasmineContent.appendChild(element)
expect(element).toHaveClass 'some'
+10 -5
Ver Arquivo
@@ -3,10 +3,12 @@ _ = require 'underscore-plus'
TextEditorView = require '../src/text-editor-view'
TextEditorComponent = require '../src/text-editor-component'
ViewRegistry = require '../src/view-registry'
nbsp = String.fromCharCode(160)
describe "TextEditorComponent", ->
[contentNode, editor, wrapperView, wrapperNode, component, componentNode, verticalScrollbarNode, horizontalScrollbarNode] = []
[viewRegistry, contentNode, editor, wrapperView, wrapperNode, component, componentNode, verticalScrollbarNode, horizontalScrollbarNode] = []
[lineHeightInPixels, charWidth, nextAnimationFrame, noAnimationFrame, lineOverdrawMargin] = []
beforeEach ->
@@ -31,19 +33,22 @@ describe "TextEditorComponent", ->
atom.project.open('sample.js').then (o) -> editor = o
runs ->
viewRegistry = new ViewRegistry(atom.views)
contentNode = document.querySelector('#jasmine-content')
contentNode.style.width = '1000px'
wrapperView = new TextEditorView(editor, {lineOverdrawMargin})
wrapperView.attachToDom()
wrapperNode = wrapperView.element
wrapperNode = atom.views.createView(editor, {viewRegistry, lineOverdrawMargin})
wrapperNode.setUpdatedSynchronously(false)
jasmine.attachToDOM(wrapperNode)
{component} = wrapperView
{component} = wrapperNode
component.setFontFamily('monospace')
component.setLineHeight(1.3)
component.setFontSize(20)
wrapperView = wrapperNode.__spacePenView
lineHeightInPixels = editor.getLineHeightInPixels()
charWidth = editor.getDefaultCharWidth()
componentNode = component.getDOMNode()
+1 -1
Ver Arquivo
@@ -228,7 +228,7 @@ describe "ThemeManager", ->
beforeEach ->
jasmine.snapshotDeprecations()
workspaceElement = atom.views.getView(atom.workspace)
workspaceElement = atom.views.createView(atom.workspace)
jasmine.attachToDOM(workspaceElement)
workspaceElement.appendChild document.createElement('atom-text-editor')
@@ -1,17 +1,17 @@
ViewRegistry = require '../src/view-registry'
ViewFactory = require '../src/view-factory'
{View} = require '../src/space-pen-extensions'
describe "ViewRegistry", ->
registry = null
describe "ViewFactory", ->
factory = null
beforeEach ->
registry = new ViewRegistry
factory = new ViewFactory
describe "::getView(object)", ->
describe "::createView(object, params)", ->
describe "when passed a DOM node", ->
it "returns the given DOM node", ->
node = document.createElement('div')
expect(registry.getView(node)).toBe node
expect(factory.createView(node)).toBe node
describe "when passed a SpacePen view", ->
it "returns the root node of the view with a __spacePenView property pointing at the SpacePen view", ->
@@ -19,56 +19,65 @@ describe "ViewRegistry", ->
@content: -> @div "Hello"
view = new TestView
node = registry.getView(view)
node = factory.createView(view)
expect(node.textContent).toBe "Hello"
expect(node.__spacePenView).toBe view
describe "when passed a model object", ->
describe "when a view provider is registered matching the object's constructor", ->
describe "when the provider has a viewConstructor property", ->
it "constructs a view element and assigns the model on it", ->
it "constructs a view element and calls initialize on it with the creation params", ->
class TestModel
class TestModelSubclass extends TestModel
class TestView
setModel: (@model) ->
initialize: (@params) ->
model = new TestModel
registry.addViewProvider
factory.addViewProvider
modelConstructor: TestModel
viewConstructor: TestView
view = registry.getView(model)
view = factory.createView(model, a: 1)
expect(view instanceof TestView).toBe true
expect(view.model).toBe model
expect(view.params.a).toBe 1
expect(view.params.model).toBe model
expect(view.params.viewFactory).toBe factory
subclassModel = new TestModelSubclass
view2 = registry.getView(subclassModel)
view2 = factory.createView(subclassModel)
expect(view2 instanceof TestView).toBe true
expect(view2.model).toBe subclassModel
expect(view2.params.model).toBe subclassModel
describe "when the provider has a createView method", ->
it "constructs a view element by calling the createView method with the model", ->
it "constructs a view element by calling the createView method with the creation params", ->
class TestModel
class TestView
setModel: (@model) ->
initialize: (@params) ->
registry.addViewProvider
factory.addViewProvider
modelConstructor: TestModel
createView: (model) ->
createView: (params) ->
view = new TestView
view.setModel(model)
view.initialize(params)
view
model = new TestModel
view = registry.getView(model)
view = factory.createView(model, a: 1)
expect(view instanceof TestView).toBe true
expect(view.model).toBe model
expect(view.params.a).toBe 1
expect(view.params.model).toBe model
describe "when no view provider is registered for the object's constructor", ->
describe "when the object has a .getViewClass() method", ->
describe "when the object has a .createViewClass() method", ->
beforeEach ->
jasmine.snapshotDeprecations()
afterEach ->
jasmine.restoreDeprecationsSnapshot()
it "builds an instance of the view class with the model, then returns its root node with a __spacePenView property pointing at the view", ->
class TestView extends View
@content: (model) -> @div model.name
@@ -79,29 +88,26 @@ describe "ViewRegistry", ->
getViewClass: -> TestView
model = new TestModel("hello")
node = registry.getView(model)
node = factory.createView(model)
expect(node.textContent).toBe "hello"
view = node.__spacePenView
expect(view instanceof TestView).toBe true
expect(view.model).toBe model
# returns the same DOM node for repeated calls
expect(registry.getView(model)).toBe node
describe "when the object has no .getViewClass() method", ->
describe "when the object has no .createViewClass() method", ->
it "throws an exception", ->
expect(-> registry.getView(new Object)).toThrow()
expect(-> factory.createView(new Object)).toThrow()
describe "::addViewProvider(providerSpec)", ->
it "returns a disposable that can be used to remove the provider", ->
class TestModel
class TestView
setModel: (@model) ->
disposable = registry.addViewProvider
initialize: ->
disposable = factory.addViewProvider
modelConstructor: TestModel
viewConstructor: TestView
expect(registry.getView(new TestModel) instanceof TestView).toBe true
expect(factory.createView(new TestModel) instanceof TestView).toBe true
disposable.dispose()
expect(-> registry.getView(new TestModel)).toThrow()
expect(-> factory.createView(new TestModel)).toThrow()
-31
Ver Arquivo
@@ -460,17 +460,6 @@ describe "Workspace", ->
describe "adding panels", ->
class TestItem
class TestItemElement extends HTMLElement
constructor: ->
setModel: (@model) ->
getModel: -> @model
beforeEach ->
atom.views.addViewProvider(
modelConstructor: TestItem
viewConstructor: TestItemElement
)
describe '::addLeftPanel(model)', ->
it 'adds a panel to the correct panel container', ->
expect(atom.workspace.getLeftPanels().length).toBe(0)
@@ -482,10 +471,6 @@ describe "Workspace", ->
expect(panel).toBeDefined()
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 0})
itemView = atom.workspace.getLeftPanels()[0].getItemView()
expect(itemView instanceof TestItemElement).toBe(true)
expect(itemView.getModel()).toBe(model)
describe '::addRightPanel(model)', ->
it 'adds a panel to the correct panel container', ->
expect(atom.workspace.getRightPanels().length).toBe(0)
@@ -497,10 +482,6 @@ describe "Workspace", ->
expect(panel).toBeDefined()
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 0})
itemView = atom.workspace.getRightPanels()[0].getItemView()
expect(itemView instanceof TestItemElement).toBe(true)
expect(itemView.getModel()).toBe(model)
describe '::addTopPanel(model)', ->
it 'adds a panel to the correct panel container', ->
expect(atom.workspace.getTopPanels().length).toBe(0)
@@ -512,10 +493,6 @@ describe "Workspace", ->
expect(panel).toBeDefined()
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 0})
itemView = atom.workspace.getTopPanels()[0].getItemView()
expect(itemView instanceof TestItemElement).toBe(true)
expect(itemView.getModel()).toBe(model)
describe '::addBottomPanel(model)', ->
it 'adds a panel to the correct panel container', ->
expect(atom.workspace.getBottomPanels().length).toBe(0)
@@ -527,10 +504,6 @@ describe "Workspace", ->
expect(panel).toBeDefined()
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 0})
itemView = atom.workspace.getBottomPanels()[0].getItemView()
expect(itemView instanceof TestItemElement).toBe(true)
expect(itemView.getModel()).toBe(model)
describe '::addModalPanel(model)', ->
it 'adds a panel to the correct panel container', ->
expect(atom.workspace.getModalPanels().length).toBe(0)
@@ -541,7 +514,3 @@ describe "Workspace", ->
expect(panel).toBeDefined()
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 0})
itemView = atom.workspace.getModalPanels()[0].getItemView()
expect(itemView instanceof TestItemElement).toBe(true)
expect(itemView.getModel()).toBe(model)
+3 -3
Ver Arquivo
@@ -15,7 +15,7 @@ describe "WorkspaceView", ->
atom.project.setPaths([atom.project.resolve('dir')])
pathToOpen = atom.project.resolve('a')
atom.workspace = new Workspace
atom.workspaceView = atom.views.getView(atom.workspace).__spacePenView
atom.workspaceView = atom.views.createView(atom.workspace).__spacePenView
atom.workspaceView.enableKeymap()
atom.workspaceView.focus()
@@ -34,7 +34,7 @@ describe "WorkspaceView", ->
atom.workspaceView.remove()
atom.project = atom.deserializers.deserialize(projectState)
atom.workspace = Workspace.deserialize(workspaceState)
atom.workspaceView = atom.views.getView(atom.workspace).__spacePenView
atom.workspaceView = atom.views.createView(atom.workspace).__spacePenView
atom.workspaceView.attachToDom()
describe "when the serialized WorkspaceView has an unsaved buffer", ->
@@ -279,7 +279,7 @@ describe "WorkspaceView", ->
describe 'panel containers', ->
workspaceElement = null
beforeEach ->
workspaceElement = atom.views.getView(atom.workspace)
workspaceElement = atom.views.createView(atom.workspace)
it 'inserts panel container elements in the correct places in the DOM', ->
leftContainer = workspaceElement.querySelector('atom-panel-container.left')
+5 -5
Ver Arquivo
@@ -39,7 +39,7 @@ class Atom extends Model
atom.workspaceView is no longer available.
In most cases you will not need the view. See the Workspace docs for
alternatives: https://atom.io/docs/api/latest/Workspace.
If you do need the view, please use `atom.views.getView(atom.workspace)`,
If you do need the view, please use `document.querySelector('atom-workspace')`,
which returns an HTMLElement.
"""
@@ -167,7 +167,7 @@ class Atom extends Model
# Public: A {DeserializerManager} instance
deserializers: null
# Public: A {ViewRegistry} instance
# Public: A {ViewFactory} instance
views: null
# Public: A {Workspace} instance
@@ -220,7 +220,7 @@ class Atom extends Model
Config = require './config'
KeymapManager = require './keymap-extensions'
ViewRegistry = require './view-registry'
ViewFactory = require './view-factory'
CommandRegistry = require './command-registry'
TooltipManager = require './tooltip-manager'
NotificationManager = require './notification-manager'
@@ -253,7 +253,7 @@ class Atom extends Model
@tooltips = new TooltipManager
@notifications = new NotificationManager
@commands = new CommandRegistry
@views = new ViewRegistry
@views = new ViewFactory
@packages = new PackageManager({devMode, configDirPath, resourcePath, safeMode})
@styles = new StyleManager
document.head.appendChild(new StylesElement)
@@ -681,7 +681,7 @@ class Atom extends Model
startTime = Date.now()
@workspace = Workspace.deserialize(@state.workspace) ? new Workspace
workspaceElement = @views.getView(@workspace)
workspaceElement = @views.createView(@workspace)
@__workspaceView = workspaceElement.__spacePenView
@deserializeTimings.workspace = Date.now() - startTime
+2 -2
Ver Arquivo
@@ -66,10 +66,10 @@ LinesComponent = React.createClass
insertionPoint = document.createElement('content')
insertionPoint.setAttribute('select', 'atom-overlay')
@overlayManager = new OverlayManager(@props.hostElement)
@overlayManager = new OverlayManager(@props.hostElement, @props.hostElement.viewRegistry)
@getDOMNode().appendChild(insertionPoint)
else
@overlayManager = new OverlayManager(@getDOMNode())
@overlayManager = new OverlayManager(@getDOMNode(), @props.hostElement.viewRegistry)
shouldComponentUpdate: (newProps) ->
return true unless isEqualForProperties(newProps, @props,
+2 -2
Ver Arquivo
@@ -1,6 +1,6 @@
module.exports =
class OverlayManager
constructor: (@container) ->
constructor: (@container, @viewRegistry) ->
@overlays = {}
render: (props) ->
@@ -25,7 +25,7 @@ class OverlayManager
return
renderOverlay: (editor, decoration, pixelPosition, lineHeightInPixels) ->
item = atom.views.getView(decoration.item)
item = @viewRegistry.getView(decoration.item)
unless overlay = @overlays[decoration.id]
overlay = @overlays[decoration.id] = document.createElement('atom-overlay')
overlay.appendChild(item)
+3 -3
Ver Arquivo
@@ -8,7 +8,7 @@ class PaneAxisElement extends HTMLElement
detachedCallback: ->
@subscriptions.dispose()
setModel: (@model) ->
initialize: ({@viewRegistry, @model}) ->
@subscriptions.add @model.onDidAddChild(@childAdded.bind(this))
@subscriptions.add @model.onDidRemoveChild(@childRemoved.bind(this))
@subscriptions.add @model.onDidReplaceChild(@childReplaced.bind(this))
@@ -22,12 +22,12 @@ class PaneAxisElement extends HTMLElement
@classList.add('vertical', 'pane-column')
childAdded: ({child, index}) ->
view = @model.getView(child)
view = @viewRegistry.getView(child)
@insertBefore(view, @children[index])
callAttachHooks(view) # for backward compatibility with SpacePen views
childRemoved: ({child}) ->
view = @model.getView(child)
view = @viewRegistry.getView(child)
view.remove()
childReplaced: ({index, oldChild, newChild}) ->
-3
Ver Arquivo
@@ -39,9 +39,6 @@ class PaneAxis extends Model
getOrientation: -> @orientation
getView: (object) ->
@container.getView(object)
getChildren: -> @children.slice()
getPanes: ->
+3 -3
Ver Arquivo
@@ -11,7 +11,7 @@ class PaneContainerElement extends HTMLElement
PaneContainerView ?= require './pane-container-view'
@__spacePenView = new PaneContainerView(this)
setModel: (@model) ->
initialize: ({@viewRegistry, @model}) ->
@subscriptions.add @model.observeRoot(@rootChanged.bind(this))
@__spacePenView.setModel(@model)
@@ -19,7 +19,7 @@ class PaneContainerElement extends HTMLElement
focusedElement = document.activeElement if @hasFocus()
@firstChild?.remove()
if root?
view = @model.getView(root)
view = @viewRegistry.getView(root)
@appendChild(view)
callAttachHooks(view)
focusedElement?.focus()
@@ -45,7 +45,7 @@ class PaneContainerElement extends HTMLElement
y = pointB.y - pointA.y
Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2))
paneView = @model.getView(@model.getActivePane())
paneView = @viewRegistry.getView(@model.getActivePane())
box = @boundingBoxForPaneView(paneView)
paneViews = _.toArray(@querySelectorAll('atom-pane'))
+3 -3
Ver Arquivo
@@ -23,7 +23,7 @@ class PaneContainerView extends View
@subscriptions.add @model.onDidChangeActivePaneItem(@onActivePaneItemChanged)
getRoot: ->
view = @model.getView(@model.getRoot())
view = @element.viewRegistry.getView(@model.getRoot())
view.__spacePenView ? view
onActivePaneItemChanged: (activeItem) =>
@@ -55,7 +55,7 @@ class PaneContainerView extends View
@getActivePaneView()
getActivePaneView: ->
@model.getView(@model.getActivePane()).__spacePenView
@element.viewRegistry.getView(@model.getActivePane()).__spacePenView
getActivePaneItem: ->
@model.getActivePaneItem()
@@ -64,7 +64,7 @@ class PaneContainerView extends View
@getActivePaneView()?.activeView
paneForUri: (uri) ->
@model.getView(@model.paneForUri(uri)).__spacePenView
@element.viewRegistry.getView(@model.paneForUri(uri)).__spacePenView
focusNextPaneView: ->
@model.activateNextPane()
+4 -9
Ver Arquivo
@@ -9,7 +9,6 @@ PaneAxisElement = require './pane-axis-element'
PaneAxis = require './pane-axis'
TextEditor = require './text-editor'
TextEditorElement = require './text-editor-element'
ViewRegistry = require './view-registry'
ItemRegistry = require './item-registry'
module.exports =
@@ -36,7 +35,6 @@ class PaneContainer extends Model
@subscriptions = new CompositeDisposable
@itemRegistry = new ItemRegistry
@viewRegistry = params?.viewRegistry ? new ViewRegistry
@registerViewProviders()
@setRoot(params?.root ? new Pane)
@@ -58,25 +56,22 @@ class PaneContainer extends Model
activePaneId: @activePane.id
registerViewProviders: ->
@viewRegistry.addViewProvider
atom.views.addViewProvider
modelConstructor: PaneContainer
viewConstructor: PaneContainerElement
@viewRegistry.addViewProvider
atom.views.addViewProvider
modelConstructor: PaneAxis
viewConstructor: PaneAxisElement
@viewRegistry.addViewProvider
atom.views.addViewProvider
modelConstructor: Pane
viewConstructor: PaneElement
@viewRegistry.addViewProvider
atom.views.addViewProvider
modelConstructor: TextEditor
viewConstructor: TextEditorElement
getView: (object) ->
@viewRegistry.getView(object)
onDidChangeRoot: (fn) ->
@emitter.on 'did-change-root', fn
+6 -6
Ver Arquivo
@@ -43,9 +43,7 @@ class PaneElement extends HTMLElement
createSpacePenShim: ->
@__spacePenView = new PaneView(this)
getModel: -> @model
setModel: (@model) ->
initialize: ({@viewRegistry, @model}) ->
@subscriptions.add @model.onDidActivate(@activated.bind(this))
@subscriptions.add @model.observeActive(@activeStatusChanged.bind(this))
@subscriptions.add @model.observeActiveItem(@activeItemChanged.bind(this))
@@ -53,6 +51,8 @@ class PaneElement extends HTMLElement
@subscriptions.add @model.onDidDestroy(@paneDestroyed.bind(this))
@__spacePenView.setModel(@model)
getModel: -> @model
activated: ->
@focus()
@@ -66,7 +66,7 @@ class PaneElement extends HTMLElement
return unless item?
hasFocus = @hasFocus()
itemView = @model.getView(item)
itemView = @viewRegistry.getView(item)
unless @itemViews.contains(itemView)
@itemViews.appendChild(itemView)
@@ -94,14 +94,14 @@ class PaneElement extends HTMLElement
itemView.style.display = 'none'
itemRemoved: ({item, index, destroyed}) ->
if viewToRemove = @model.getView(item)
if viewToRemove = @viewRegistry.getView(item)
callRemoveHooks(viewToRemove) if destroyed
viewToRemove.remove()
paneDestroyed: ->
@subscriptions.dispose()
getActiveView: -> @model.getView(@model.getActiveItem())
getActiveView: -> @viewRegistry.getView(@model.getActiveItem())
hasFocus: ->
this is document.activeElement or @contains(document.activeElement)
+5 -5
Ver Arquivo
@@ -153,15 +153,15 @@ class PaneView extends View
activeItemModifiedChanged: =>
@trigger 'pane:active-item-modified-status-changed'
@::accessor 'activeView', -> @model.getView(@activeItem)?.__spacePenView
@::accessor 'activeView', -> @element.viewRegistry.getView(@activeItem)?.__spacePenView
splitLeft: (items...) -> @model.getView(@model.splitLeft({items})).__spacePenView
splitLeft: (items...) -> @element.viewRegistry.getView(@model.splitLeft({items})).__spacePenView
splitRight: (items...) -> @model.getView(@model.splitRight({items})).__spacePenView
splitRight: (items...) -> @element.viewRegistry.getView(@model.splitRight({items})).__spacePenView
splitUp: (items...) -> @model.getView(@model.splitUp({items})).__spacePenView
splitUp: (items...) -> @element.viewRegistry.getView(@model.splitUp({items})).__spacePenView
splitDown: (items...) -> @model.getView(@model.splitDown({items})).__spacePenView
splitDown: (items...) -> @element.viewRegistry.getView(@model.splitDown({items})).__spacePenView
getContainer: -> @closest('atom-pane-container').view()
-3
Ver Arquivo
@@ -53,9 +53,6 @@ class Pane extends Model
params.activeItem = find params.items, (item) -> item.getUri?() is activeItemUri
params
getView: (object) ->
@container.getView(object)
getParent: -> @parent
setParent: (@parent) -> @parent
+3 -3
Ver Arquivo
@@ -6,14 +6,14 @@ class PanelContainerElement extends HTMLElement
getModel: -> @model
setModel: (@model) ->
initialize: ({@viewRegistry, @model}) ->
@subscriptions.add @model.onDidAddPanel(@panelAdded.bind(this))
@subscriptions.add @model.onDidRemovePanel(@panelRemoved.bind(this))
@subscriptions.add @model.onDidDestroy(@destroyed.bind(this))
@classList.add(@model.getLocation())
panelAdded: ({panel, index}) ->
panelElement = panel.getView()
panelElement = @viewRegistry.getView(panel)
panelElement.classList.add(@model.getLocation())
if @model.isModal()
panelElement.classList.add("overlay", "from-top")
@@ -32,7 +32,7 @@ class PanelContainerElement extends HTMLElement
@hideAllPanelsExcept(panel) if visible
panelRemoved: ({panel, index}) ->
@removeChild(panel.getView())
@removeChild(@viewRegistry.getView(panel))
destroyed: ->
@subscriptions.dispose()
+1 -3
Ver Arquivo
@@ -2,7 +2,7 @@
module.exports =
class PanelContainer
constructor: ({@viewRegistry, @location}) ->
constructor: ({@location}={}) ->
@emitter = new Emitter
@subscriptions = new CompositeDisposable
@panels = []
@@ -30,8 +30,6 @@ class PanelContainer
Section: Panels
###
getView: -> @viewRegistry.getView(this)
getLocation: -> @location
isModal: -> @location is 'modal'
+6 -4
Ver Arquivo
@@ -7,16 +7,18 @@ class PanelElement extends HTMLElement
getModel: -> @model
setModel: (@model) ->
view = @model.getItemView()
@appendChild(view)
initialize: ({@viewRegistry, @model}) ->
@appendChild(@getItemView())
@classList.add(@model.getClassName().split(' ')...) if @model.getClassName()?
@subscriptions.add @model.onDidChangeVisible(@visibleChanged.bind(this))
@subscriptions.add @model.onDidDestroy(@destroyed.bind(this))
getItemView: ->
@viewRegistry.getView(@model.getItem())
attachedCallback: ->
callAttachHooks(@model.getItemView()) # for backward compatibility with SpacePen views
callAttachHooks(@getItemView()) # for backward compatibility with SpacePen views
@visibleChanged(@model.isVisible())
visibleChanged: (visible) ->
+3 -10
Ver Arquivo
@@ -14,7 +14,7 @@ class Panel
Section: Construction and Destruction
###
constructor: ({@viewRegistry, @item, @visible, @priority, @className}) ->
constructor: ({@item, @visible, @priority, @className}) ->
@emitter = new Emitter
@visible ?= true
@priority ?= 100
@@ -50,15 +50,8 @@ class Panel
Section: Panel Details
###
# Public: Gets this panel model's view DOM node.
#
# Returns an `<atom-panel>` {Element}
getView: -> @viewRegistry.getView(this)
# Public: Gets your panel contents view.
#
# Returns an {Element} or jQuery element, depeneding on how you created the panel.
getItemView: -> @viewRegistry.getView(@item)
# Public: Returns the panel's item.
getItem: -> @item
# Public: Returns a {Number} indicating this panel's priority.
getPriority: -> @priority
+3
Ver Arquivo
@@ -63,6 +63,9 @@ class TextEditorElement extends HTMLElement
@component.checkForVisibilityChange()
@focus() if @focusOnAttach
initialize: ({@viewRegistry, @lineOverdrawMargin, model}) ->
@setModel(model)
setModel: (model) ->
throw new Error("Model already assigned on TextEditorElement") if @model?
return if model.isDestroyed()
+1 -1
Ver Arquivo
@@ -63,7 +63,7 @@ class TextEditorView extends View
element = new TextEditorElement
element.lineOverdrawMargin = props?.lineOverdrawMargin
element.setAttribute(name, value) for name, value of attributes if attributes?
element.setModel(model)
element.initialize({model})
return element.__spacePenView
# Handle construction with an element
+8 -6
Ver Arquivo
@@ -333,16 +333,18 @@ class ThemeManager
isInitialLoadComplete: -> @initialLoadComplete
# FIXME: This should be moved to WorkspaceElement
addActiveThemeClasses: ->
workspaceElement = atom.views.getView(atom.workspace)
for pack in @getActiveThemes()
workspaceElement.classList.add("theme-#{pack.name}")
if workspaceElement = document.querySelector('atom-workspace')
for pack in @getActiveThemes()
workspaceElement.classList.add("theme-#{pack.name}")
return
# FIXME: This should be moved to WorkspaceElement
removeActiveThemeClasses: ->
workspaceElement = atom.views.getView(atom.workspace)
for pack in @getActiveThemes()
workspaceElement.classList.remove("theme-#{pack.name}")
if workspaceElement = document.querySelector('atom-workspace')
for pack in @getActiveThemes()
workspaceElement.classList.remove("theme-#{pack.name}")
return
refreshLessCache: ->
+106
Ver Arquivo
@@ -0,0 +1,106 @@
{Disposable} = require 'event-kit'
Grim = require 'grim'
ViewRegistry = require './view-registry'
# Essential: The `ViewFactory` can creates the appropriate views for a given
# model object based on recipes registered via {::addViewProvider}. It is
# available via `atom.views` as a singleton object.
module.exports =
class ViewFactory
constructor: ->
@providers = []
@deprecatedViewRegistry = new ViewRegistry(this)
# Essential: Add a provider that will be used by {::createView} to construct
# an element based on the constructor of the given model object.
#
# ## Examples
#
# Text editors are divided into a model and a view layer, so when you interact
# with methods like `atom.workspace.getActiveTextEditor()` you're only going
# to get the model object. We display text editors on screen by teaching the
# workspace what view constructor it should use to represent them:
#
# ```coffee
# atom.views.addViewProvider
# modelConstructor: TextEditor
# viewConstructor: TextEditorElement
# ```
#
# * `providerSpec` {Object} containing the following keys:
# * `modelConstructor` Constructor {Function} for your model.
# * `viewConstructor` (Optional) Constructor {Function} for your view. It
# should be a subclass of `HTMLElement` (that is, your view should be a
# DOM node) and have a `::setModel()` method which will be called
# immediately after construction. If you don't supply this property, you
# must supply the `createView` property with a function that never returns
# `undefined`.
# * `createView` (Optional) Factory {Function} that must return a subclass
# of `HTMLElement` or `undefined`. If this property is not present or the
# function returns `undefined`, the view provider will fall back to the
# `viewConstructor` property. If you don't provide this property, you must
# provider a `viewConstructor` property.
#
# Returns a {Disposable} on which `.dispose()` can be called to remove the
# added provider.
addViewProvider: (providerSpec) ->
@providers.push(providerSpec)
new Disposable =>
@providers = @providers.filter (provider) -> provider isnt providerSpec
getView: (object, suppressDeprecationWarning) ->
unless suppressDeprecationWarning
Grim.deprecate("Call ::getView on the workspace element instead. The atom.views global is only intended to create views.")
@deprecatedViewRegistry.getView(object)
# Essential: Create an element for the given model object based on providers
# registered via {::addViewProvider}.
#
# ## Examples
#
# ### Creating a workspace element in specs
# ```coffee
# workspaceElement = atom.views.createView(atom.workspace)
# ```
#
# * `object` The model for which to create the view. A view provider matching
# its constructor must be registered.
# * `params` (optional) An {Object} with which to initialize the view. If the
# selected view provider has a `createView` method, the params will be
# passed to it. If the view provider has a `viewConstructor` method,
# `initialize` will be called on the element after creation with the
# given params.
#
# Returns a DOM element.
createView: (object, params) ->
view =
if object instanceof HTMLElement
object
else if object?.jquery
object[0]?.__spacePenView ?= object
object[0]
else if provider = @findProvider(object)
params ?= {}
params.viewFactory = this
params.model = object
element = provider.createView?(params)
unless element?
element = new provider.viewConstructor
if not (typeof element.initialize is 'function') and (typeof element.setModel is 'function')
Grim.deprecate("Define `::initialize` instead of `::setModel` in your view. It will be passed a params hash including the model.")
element.setModel(object)
else
element.initialize(params)
element
else if viewConstructor = object?.getViewClass?()
Grim.deprecate("Add a view provider for your object on atom.views instead of implementing `::getViewClass`.")
view = new viewConstructor(object)
view[0].__spacePenView ?= view
view[0]
else
throw new Error("Can't create a view for #{object.constructor.name} instance. Please register a view provider.")
@deprecatedViewRegistry.views.set(object, view)
view
findProvider: (object) ->
@providers.find ({modelConstructor}) -> object instanceof modelConstructor
+2 -132
Ver Arquivo
@@ -1,144 +1,14 @@
{Disposable} = require 'event-kit'
# Essential: `ViewRegistry` handles the association between model and view
# types in Atom. We call this association a View Provider. As in, for a given
# model, this class can provide a view via {::getView}, as long as the
# model/view association was registered via {::addViewProvider}
#
# If you're adding your own kind of pane item, a good strategy for all but the
# simplest items is to separate the model and the view. The model handles
# application logic and is the primary point of API interaction. The view
# just handles presentation.
#
# View providers to inform the workspace how your model objects should be
# presented in the DOM. A view provider must always return a DOM node, which
# makes [HTML 5 custom elements](http://www.html5rocks.com/en/tutorials/webcomponents/customelements/)
# an ideal tool for implementing views in Atom.
#
# You can access the `ViewRegistry` object via `atom.views`.
#
# ## Examples
#
# ### Getting the workspace element
#
# ```coffee
# workspaceElement = atom.views.getView(atom.workspace)
# ```
#
# ### Getting An Editor Element
#
# ```coffee
# textEditor = atom.workspace.getActiveTextEditor()
# textEditorElement = atom.views.getView(textEditor)
# ```
#
# ### Getting A Pane Element
#
# ```coffee
# pane = atom.workspace.getActivePane()
# paneElement = atom.views.getView(pane)
# ```
module.exports =
class ViewRegistry
constructor: ->
constructor: (@viewFactory) ->
@views = new WeakMap
@providers = []
# Essential: Add a provider that will be used to construct views in the
# workspace's view layer based on model objects in its model layer.
#
# ## Examples
#
# Text editors are divided into a model and a view layer, so when you interact
# with methods like `atom.workspace.getActiveTextEditor()` you're only going
# to get the model object. We display text editors on screen by teaching the
# workspace what view constructor it should use to represent them:
#
# ```coffee
# atom.views.addViewProvider
# modelConstructor: TextEditor
# viewConstructor: TextEditorElement
# ```
#
# * `providerSpec` {Object} containing the following keys:
# * `modelConstructor` Constructor {Function} for your model.
# * `viewConstructor` (Optional) Constructor {Function} for your view. It
# should be a subclass of `HTMLElement` (that is, your view should be a
# DOM node) and have a `::setModel()` method which will be called
# immediately after construction. If you don't supply this property, you
# must supply the `createView` property with a function that never returns
# `undefined`.
# * `createView` (Optional) Factory {Function} that must return a subclass
# of `HTMLElement` or `undefined`. If this property is not present or the
# function returns `undefined`, the view provider will fall back to the
# `viewConstructor` property. If you don't provide this property, you must
# provider a `viewConstructor` property.
#
# Returns a {Disposable} on which `.dispose()` can be called to remove the
# added provider.
addViewProvider: (providerSpec) ->
@providers.push(providerSpec)
new Disposable =>
@providers = @providers.filter (provider) -> provider isnt providerSpec
# Essential: Get the view associated with an object in the workspace.
#
# If you're just *using* the workspace, you shouldn't need to access the view
# layer, but view layer access may be necessary if you want to perform DOM
# manipulation that isn't supported via the model API.
#
# ## Examples
#
# ### Getting An Editor Element
# ```coffee
# textEditor = atom.workspace.getActiveTextEditor()
# textEditorElement = atom.views.getView(textEditor)
# ```
#
# ### Getting A Pane Element
# ```coffee
# pane = atom.workspace.getActivePane()
# paneElement = atom.views.getView(pane)
# ```
#
# ### Getting The Workspace Element
#
# ```coffee
# workspaceElement = atom.views.getView(atom.workspace)
# ```
#
# * `object` The object for which you want to retrieve a view. This can be a
# pane item, a pane, or the workspace itself.
#
# Returns a DOM element.
getView: (object) ->
return unless object?
if view = @views.get(object)
view
else
view = @createView(object)
view = @viewFactory.createView(object, viewRegistry: this)
@views.set(object, view)
view
createView: (object) ->
if object instanceof HTMLElement
object
else if object?.jquery
object[0]?.__spacePenView ?= object
object[0]
else if provider = @findProvider(object)
element = provider.createView?(object)
unless element?
element = new provider.viewConstructor
element.setModel(object)
element
else if viewConstructor = object?.getViewClass?()
view = new viewConstructor(object)
view[0].__spacePenView ?= view
view[0]
else
throw new Error("Can't create a view for #{object.constructor.name} instance. Please register a view provider.")
findProvider: (object) ->
@providers.find ({modelConstructor}) -> object instanceof modelConstructor
+4 -2
Ver Arquivo
@@ -32,12 +32,14 @@ class WindowEventHandler
# FIXME: Remove this when deprecations are removed
{releaseVersion, releaseNotes} = detail
detail = [releaseVersion, releaseNotes]
atom.commands.dispatch atom.views.getView(atom.workspace), "window:update-available", detail
if workspaceElement = document.querySelector('atom-workspace')
atom.commands.dispatch workspaceElement, "window:update-available", detail
@subscribe ipc, 'command', (command, args...) ->
activeElement = document.activeElement
# Use the workspace element view if body has focus
if activeElement is document.body and workspaceElement = atom.views.getView(atom.workspace)
if activeElement is document.body and workspaceElement = document.querySelector('atom-workspace')
activeElement = workspaceElement
atom.commands.dispatch(activeElement, command, args[0])
+63 -8
Ver Arquivo
@@ -6,9 +6,37 @@ scrollbarStyle = require 'scrollbar-style'
{callAttachHooks} = require 'space-pen'
WorkspaceView = null
# Essential: The on-screen representation of the workspace. Unless you have
# an explicit need access the view layer, you should prefer using the
# {Workspace} model object via `atom.workspace`.
#
# ## Examples
#
# In specs, you can create a workspace element via the view factory and attach
# it to the DOM:
#
# ```coffee
# workspaceElement = atom.views.createElement(atom.workspace)
# jasmine.attachToDOM(workspaceElement)
#
# # Get a reference to a nested element corresponding to a model object...
# editorElement = workspaceElement.getView(atom.workspace.getActiveTextEditor)
# ```
#
# In production, you can access the singleton instance of the workspace element
# by pulling it directly from the DOM:
#
# ```coffee
# workspaceElement = document.querySelector('atom-workspace')
#
# # Careful! Direct DOM manipulation is more likely to break as Atom changes
# workspaceElement.addClass("foo")
# ```
module.exports =
class WorkspaceElement extends HTMLElement
globalTextEditorStyleSheet: null
viewRegistry: null
model: null
createdCallback: ->
@subscriptions = new CompositeDisposable
@@ -62,19 +90,20 @@ class WorkspaceElement extends HTMLElement
WorkspaceView ?= require './workspace-view'
@__spacePenView = new WorkspaceView(this)
getModel: -> @model
initialize: ({@viewFactory, @model}) ->
@viewRegistry = @viewFactory.deprecatedViewRegistry
atom.views.deprecatedViewRegistry = @viewRegistry
setModel: (@model) ->
@paneContainer = atom.views.getView(@model.paneContainer)
@paneContainer = @viewRegistry.getView(@model.paneContainer)
@verticalAxis.appendChild(@paneContainer)
@addEventListener 'focus', @handleFocus.bind(this)
@panelContainers =
top: @model.panelContainers.top.getView()
left: @model.panelContainers.left.getView()
right: @model.panelContainers.right.getView()
bottom: @model.panelContainers.bottom.getView()
modal: @model.panelContainers.modal.getView()
top: @viewRegistry.getView(@model.panelContainers.top)
left: @viewRegistry.getView(@model.panelContainers.left)
right: @viewRegistry.getView(@model.panelContainers.right)
bottom: @viewRegistry.getView(@model.panelContainers.bottom)
modal: @viewRegistry.getView(@model.panelContainers.modal)
@horizontalAxis.insertBefore(@panelContainers.left, @verticalAxis)
@horizontalAxis.appendChild(@panelContainers.right)
@@ -86,6 +115,32 @@ class WorkspaceElement extends HTMLElement
@__spacePenView.setModel(@model)
getModel: -> @model
# Essential: Get the view associated with a model in the workspace.
#
# ## Examples
#
# ### Get the active text editor's view element
# ```coffee
# # At the model level...
# activeTextEditor = atom.workspace.getActiveTextEditor()
#
# # At the view level...
# workspaceElement = document.querySelector('atom-workspace')
# textEditorElement = workspaceElement.getView(activeTextEditor)
#
# # Now manipulate the text editor's DOM at your own risk...
# ```
#
# * `model` A model object that's present in the workspace. It could be a
# workspace model object such as a {Pane} or a {Panel}, or it could be a
# third-party model such as a pane or panel's *item*.
#
# Returns a DOM element.
getView: (model) ->
@viewRegistry.getView(model)
setTextEditorFontSize: (fontSize) ->
@updateGlobalEditorStyle('font-size', fontSize + 'px')
+1 -1
Ver Arquivo
@@ -59,7 +59,7 @@ class WorkspaceView extends View
constructor: (@element) ->
unless @element?
return atom.views.getView(atom.workspace).__spacePenView
return atom.views.getView(atom.workspace, true).__spacePenView
super
@deprecateViewEvents()
+16 -21
Ver Arquivo
@@ -14,7 +14,6 @@ Panel = require './panel'
PanelElement = require './panel-element'
PanelContainer = require './panel-container'
PanelContainerElement = require './panel-container-element'
ViewRegistry = require './view-registry'
WorkspaceElement = require './workspace-element'
# Essential: Represents the state of the user interface for the entire window.
@@ -34,7 +33,6 @@ class Workspace extends Model
@delegatesProperty 'activePane', 'activePaneItem', toProperty: 'paneContainer'
@properties
viewRegistry: null
paneContainer: null
fullScreen: false
destroyedItemUris: -> []
@@ -45,16 +43,15 @@ class Workspace extends Model
@emitter = new Emitter
@openers = []
viewRegistry = atom.views
@paneContainer ?= new PaneContainer({viewRegistry})
@paneContainer ?= new PaneContainer()
@paneContainer.onDidDestroyPaneItem(@onPaneItemDestroyed)
@panelContainers =
top: new PanelContainer({viewRegistry, location: 'top'})
left: new PanelContainer({viewRegistry, location: 'left'})
right: new PanelContainer({viewRegistry, location: 'right'})
bottom: new PanelContainer({viewRegistry, location: 'bottom'})
modal: new PanelContainer({viewRegistry, location: 'modal'})
top: new PanelContainer({location: 'top'})
left: new PanelContainer({location: 'left'})
right: new PanelContainer({location: 'right'})
bottom: new PanelContainer({location: 'bottom'})
modal: new PanelContainer({location: 'modal'})
@subscribeToActiveItem()
@@ -86,7 +83,6 @@ class Workspace extends Model
for packageName in params.packagesWithActiveGrammars ? []
atom.packages.getLoadedPackage(packageName)?.loadGrammarsSync()
params.paneContainer.viewRegistry = atom.views
params.paneContainer = PaneContainer.deserialize(params.paneContainer)
params
@@ -627,8 +623,8 @@ class Workspace extends Model
#
# * `options` {Object}
# * `item` Your panel content. It can be DOM element, a jQuery element, or
# a model with a view registered via {ViewRegistry::addViewProvider}. We recommend the
# latter. See {ViewRegistry::addViewProvider} for more information.
# a model with a view registered via {ViewFactory::addViewProvider}. We recommend the
# latter. See {ViewFactory::addViewProvider} for more information.
# * `visible` (optional) {Boolean} false if you want the panel to initially be hidden
# (default: true)
# * `priority` (optional) {Number} Determines stacking order. Lower priority items are
@@ -646,8 +642,8 @@ class Workspace extends Model
#
# * `options` {Object}
# * `item` Your panel content. It can be DOM element, a jQuery element, or
# a model with a view registered via {ViewRegistry::addViewProvider}. We recommend the
# latter. See {ViewRegistry::addViewProvider} for more information.
# a model with a view registered via {ViewFactory::addViewProvider}. We recommend the
# latter. See {ViewFactory::addViewProvider} for more information.
# * `visible` (optional) {Boolean} false if you want the panel to initially be hidden
# (default: true)
# * `priority` (optional) {Number} Determines stacking order. Lower priority items are
@@ -665,8 +661,8 @@ class Workspace extends Model
#
# * `options` {Object}
# * `item` Your panel content. It can be DOM element, a jQuery element, or
# a model with a view registered via {ViewRegistry::addViewProvider}. We recommend the
# latter. See {ViewRegistry::addViewProvider} for more information.
# a model with a view registered via {ViewFactory::addViewProvider}. We recommend the
# latter. See {ViewFactory::addViewProvider} for more information.
# * `visible` (optional) {Boolean} false if you want the panel to initially be hidden
# (default: true)
# * `priority` (optional) {Number} Determines stacking order. Lower priority items are
@@ -684,8 +680,8 @@ class Workspace extends Model
#
# * `options` {Object}
# * `item` Your panel content. It can be DOM element, a jQuery element, or
# a model with a view registered via {ViewRegistry::addViewProvider}. We recommend the
# latter. See {ViewRegistry::addViewProvider} for more information.
# a model with a view registered via {ViewFactory::addViewProvider}. We recommend the
# latter. See {ViewFactory::addViewProvider} for more information.
# * `visible` (optional) {Boolean} false if you want the panel to initially be hidden
# (default: true)
# * `priority` (optional) {Number} Determines stacking order. Lower priority items are
@@ -703,8 +699,8 @@ class Workspace extends Model
#
# * `options` {Object}
# * `item` Your panel content. It can be DOM element, a jQuery element, or
# a model with a view registered via {ViewRegistry::addViewProvider}. We recommend the
# latter. See {ViewRegistry::addViewProvider} for more information.
# a model with a view registered via {ViewFactory::addViewProvider}. We recommend the
# latter. See {ViewFactory::addViewProvider} for more information.
# * `visible` (optional) {Boolean} false if you want the panel to initially be hidden
# (default: true)
# * `priority` (optional) {Number} Determines stacking order. Lower priority items are
@@ -719,5 +715,4 @@ class Workspace extends Model
addPanel: (location, options) ->
options ?= {}
options.viewRegistry = atom.views
@panelContainers[location].addPanel(new Panel(options))