From b91c353d2b551c4978962b8079949694b012e10b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki & Nathan Sobo Date: Fri, 14 Dec 2012 11:08:18 -0800 Subject: [PATCH] Add `View#observeConfig` as a space-pen extension --- spec/stdlib/space-pen-extensions-spec.coffee | 41 +++++++++++++++++++ src/app/config.coffee | 5 ++- src/app/window.coffee | 1 + src/extensions/tree-view/src/tree-view.coffee | 2 +- src/stdlib/space-pen-extensions.coffee | 19 +++++++++ 5 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 spec/stdlib/space-pen-extensions-spec.coffee create mode 100644 src/stdlib/space-pen-extensions.coffee diff --git a/spec/stdlib/space-pen-extensions-spec.coffee b/spec/stdlib/space-pen-extensions-spec.coffee new file mode 100644 index 000000000..fecda73fa --- /dev/null +++ b/spec/stdlib/space-pen-extensions-spec.coffee @@ -0,0 +1,41 @@ +{View, $$} = require 'space-pen' + +describe "SpacePen extensions", -> + class TestView extends View + @content: -> @div() + + [view, parent, observeHandler] = [] + + beforeEach -> + view = new TestView + parent = $$ -> @div() + parent.append(view) + observeHandler = jasmine.createSpy("observeHandler") + view.observeConfig "foo.bar", observeHandler + expect(view.hasParent()).toBeTruthy() + + describe "View#observeConfig(keyPath, callback)", -> + it "observes the keyPath and destroys the subscription when unsubscribe is called", -> + expect(observeHandler).toHaveBeenCalledWith(undefined) + observeHandler.reset() + + config.foo = { bar: "hello" } + config.update() + + expect(observeHandler).toHaveBeenCalledWith("hello") + observeHandler.reset() + + view.unsubscribe() + + config.foo.bar = "goodbye" + config.update() + + expect(observeHandler).not.toHaveBeenCalled() + + it "unsubscribes on remove", -> + observeHandler.reset() + view.remove() + expect(view.hasParent()).toBeFalsy() + config.foo = { bar: "hello" } + config.update() + expect(observeHandler).not.toHaveBeenCalled() diff --git a/src/app/config.coffee b/src/app/config.coffee index 610f3e216..e0908173e 100644 --- a/src/app/config.coffee +++ b/src/app/config.coffee @@ -50,11 +50,14 @@ class Config observe: (keyPathString, callback) -> keyPath = keyPathString.split('.') value = @valueAtKeyPath(keyPath) - @on 'update', => + updateCallback = => newValue = @valueAtKeyPath(keyPath) unless newValue == value value = newValue callback(value) + subscription = { destroy: => @off 'update', updateCallback } + @on 'update', updateCallback callback(value) + subscription _.extend Config.prototype, EventEmitter diff --git a/src/app/window.coffee b/src/app/window.coffee index 115dd6ba1..c507c10e7 100644 --- a/src/app/window.coffee +++ b/src/app/window.coffee @@ -13,6 +13,7 @@ RootView = require 'root-view' Pasteboard = require 'pasteboard' require 'jquery-extensions' require 'underscore-extensions' +require 'space-pen-extensions' windowAdditions = rootViewParentSelector: 'body' diff --git a/src/extensions/tree-view/src/tree-view.coffee b/src/extensions/tree-view/src/tree-view.coffee index 2d868e62d..fc7b27e9c 100644 --- a/src/extensions/tree-view/src/tree-view.coffee +++ b/src/extensions/tree-view/src/tree-view.coffee @@ -65,7 +65,7 @@ class TreeView extends ScrollView @rootView.command 'tree-view:reveal-active-file', => @revealActiveFile() @rootView.on 'active-editor-path-change', => @selectActiveFile() @rootView.project.on 'path-change', => @updateRoot() - config.observe 'core.hideGitIgnoredFiles', => @updateRoot() + @observeConfig 'core.hideGitIgnoredFiles', => @updateRoot() @selectEntry(@root) if @root diff --git a/src/stdlib/space-pen-extensions.coffee b/src/stdlib/space-pen-extensions.coffee new file mode 100644 index 000000000..211eb845a --- /dev/null +++ b/src/stdlib/space-pen-extensions.coffee @@ -0,0 +1,19 @@ +_ = require 'underscore' +{View} = require 'space-pen' + +originalRemove = View.prototype.remove + +_.extend View.prototype, + observeConfig: (keyPath, callback) -> + @subscribe(config.observe(keyPath, callback)) + + subscribe: (subscription) -> + @subscriptions ?= [] + @subscriptions.push(subscription) + + unsubscribe: -> + subscription.destroy() for subscription in @subscriptions ? [] + + remove: (args...) -> + @unsubscribe() + originalRemove.apply(this, args)