Make model constructor argument to addViewProvider optional

This commit is contained in:
Max Brunsfeld
2015-11-19 15:54:47 -08:00
parent a0a402c3f8
commit 91b651e86c
2 changed files with 59 additions and 22 deletions

View File

@@ -47,6 +47,21 @@ describe "ViewRegistry", ->
expect(view2 instanceof TestView).toBe true
expect(view2.model).toBe subclassModel
describe "when a view provider is registered generically, and works with the object", ->
it "constructs a view element and assigns the model on it", ->
model = {a: 'b'}
registry.addViewProvider (model) ->
if model.a is 'b'
element = document.createElement('div')
element.className = 'test-element'
element
view = registry.getView({a: 'b'})
expect(view.className).toBe 'test-element'
expect(-> registry.getView({a: 'c'})).toThrow()
describe "when no view provider is registered for the object's constructor", ->
it "throws an exception", ->
expect(-> registry.getView(new Object)).toThrow()

View File

@@ -3,6 +3,8 @@ Grim = require 'grim'
{Disposable} = require 'event-kit'
_ = require 'underscore-plus'
AnyConstructor = Symbol('any-constructor')
# 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
@@ -76,16 +78,27 @@ class ViewRegistry
# textEditorElement
# ```
#
# * `modelConstructor` Constructor {Function} for your model.
# * `modelConstructor` (optional) Constructor {Function} for your model. If
# a constructor is given, the `createView` function will only be used
# for model objects inheriting from that constructor. Otherwise, it will
# will be called for any object.
# * `createView` Factory {Function} that is passed an instance of your model
# and must return a subclass of `HTMLElement` or `undefined`.
# and must return a subclass of `HTMLElement` or `undefined`. If it returns
# `undefined`, then the registry will continue to search for other view
# providers.
#
# Returns a {Disposable} on which `.dispose()` can be called to remove the
# added provider.
addViewProvider: (modelConstructor, createView) ->
if arguments.length is 1
Grim.deprecate("atom.views.addViewProvider now takes 2 arguments: a model constructor and a createView function. See docs for details.")
provider = modelConstructor
switch typeof modelConstructor
when 'function'
provider = {createView: modelConstructor, modelConstructor: AnyConstructor}
when 'object'
Grim.deprecate("atom.views.addViewProvider now takes 2 arguments: a model constructor and a createView function. See docs for details.")
provider = modelConstructor
else
throw new TypeError("Arguments to addViewProvider must be functions")
else
provider = {modelConstructor, createView}
@@ -153,25 +166,34 @@ class ViewRegistry
createView: (object) ->
if object instanceof HTMLElement
object
else if object?.element instanceof HTMLElement
object.element
else if object?.jquery
object[0]
else if provider = @findProvider(object)
element = provider.createView?(object, @atomEnvironment)
unless element?
element = new provider.viewConstructor
element.initialize?(object) ? element.setModel?(object)
element
else if viewConstructor = object?.getViewClass?()
view = new viewConstructor(object)
view[0]
else
throw new Error("Can't create a view for #{object.constructor.name} instance. Please register a view provider.")
return object
findProvider: (object) ->
find @providers, ({modelConstructor}) -> object instanceof modelConstructor
if object?.element instanceof HTMLElement
return object.element
if object?.jquery
return object[0]
for provider in @providers
if provider.modelConstructor is AnyConstructor
if element = provider.createView(object, @atomEnvironment)
return element
continue
if object instanceof provider.modelConstructor
if element = provider.createView?(object, @atomEnvironment)
return element
if viewConstructor = provider.viewConstructor
element = new viewConstructor
element.initialize?(object) ? element.setModel?(object)
return element
if viewConstructor = object?.getViewClass?()
view = new viewConstructor(object)
return view[0]
throw new Error("Can't create a view for #{object.constructor.name} instance. Please register a view provider.")
updateDocument: (fn) ->
@documentWriters.push(fn)