From 4f604ced3c7f004b62c648a8e0dceb25b0c4155d Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 13 Jan 2014 13:29:00 -0700 Subject: [PATCH 1/6] Rename Pane to PaneView --- spec/pane-container-spec.coffee | 8 ++++---- ...{pane-spec.coffee => pane-view-spec.coffee} | 6 +++--- spec/workspace-view-spec.coffee | 6 +++--- src/pane-axis.coffee | 6 +++--- src/pane-container.coffee | 6 +++--- src/pane-model.coffee | 4 ++-- src/{pane.coffee => pane-view.coffee} | 2 +- src/workspace-view.coffee | 18 +++++++++--------- 8 files changed, 28 insertions(+), 28 deletions(-) rename spec/{pane-spec.coffee => pane-view-spec.coffee} (99%) rename src/{pane.coffee => pane-view.coffee} (99%) diff --git a/spec/pane-container-spec.coffee b/spec/pane-container-spec.coffee index 374b84a00..b2a861196 100644 --- a/spec/pane-container-spec.coffee +++ b/spec/pane-container-spec.coffee @@ -1,7 +1,7 @@ path = require 'path' temp = require 'temp' PaneContainer = require '../src/pane-container' -Pane = require '../src/pane' +PaneView = require '../src/pane-view' {_, $, View, $$} = require 'atom' describe "PaneContainer", -> @@ -19,7 +19,7 @@ describe "PaneContainer", -> isEqual: (other) -> @name is other?.name container = new PaneContainer - pane1 = new Pane(new TestView('1')) + pane1 = new PaneView(new TestView('1')) container.setRoot(pane1) pane2 = pane1.splitRight(new TestView('2')) pane3 = pane2.splitDown(new TestView('3')) @@ -148,7 +148,7 @@ describe "PaneContainer", -> container = new PaneContainer container.attachToDom() - pane1 = new Pane(item1a) + pane1 = new PaneView(item1a) container.setRoot(pane1) activeItemChangedHandler = jasmine.createSpy("activeItemChangedHandler") @@ -160,7 +160,7 @@ describe "PaneContainer", -> expect(container.getPanes().length).toBe 0 activeItemChangedHandler.reset() - pane = new Pane(item1a) + pane = new PaneView(item1a) container.setRoot(pane) expect(activeItemChangedHandler.callCount).toBe 1 expect(activeItemChangedHandler.argsForCall[0][1]).toEqual item1a diff --git a/spec/pane-spec.coffee b/spec/pane-view-spec.coffee similarity index 99% rename from spec/pane-spec.coffee rename to spec/pane-view-spec.coffee index d1d031240..d609d501a 100644 --- a/spec/pane-spec.coffee +++ b/spec/pane-view-spec.coffee @@ -1,10 +1,10 @@ PaneContainer = require '../src/pane-container' -Pane = require '../src/pane' +PaneView = require '../src/pane-view' {fs, $, View} = require 'atom' path = require 'path' temp = require 'temp' -describe "Pane", -> +describe "PaneView", -> [container, view1, view2, editor1, editor2, pane] = [] class TestView extends View @@ -22,7 +22,7 @@ describe "Pane", -> view2 = new TestView(id: 'view-2', text: 'View 2') editor1 = atom.project.openSync('sample.js') editor2 = atom.project.openSync('sample.txt') - pane = new Pane(view1, editor1, view2, editor2) + pane = new PaneView(view1, editor1, view2, editor2) container.setRoot(pane) afterEach -> diff --git a/spec/workspace-view-spec.coffee b/spec/workspace-view-spec.coffee index a47854dae..f91fb8845 100644 --- a/spec/workspace-view-spec.coffee +++ b/spec/workspace-view-spec.coffee @@ -2,7 +2,7 @@ Q = require 'q' path = require 'path' temp = require 'temp' -Pane = require '../src/pane' +PaneView = require '../src/pane-view' describe "WorkspaceView", -> pathToOpen = null @@ -212,7 +212,7 @@ describe "WorkspaceView", -> describe ".openSync(filePath, options)", -> describe "when there is no active pane", -> beforeEach -> - spyOn(Pane.prototype, 'focus') + spyOn(PaneView.prototype, 'focus') atom.workspaceView.getActivePane().remove() expect(atom.workspaceView.getActivePane()).toBeUndefined() @@ -360,7 +360,7 @@ describe "WorkspaceView", -> describe ".open(filePath)", -> beforeEach -> - spyOn(Pane.prototype, 'focus') + spyOn(PaneView.prototype, 'focus') describe "when there is no active pane", -> beforeEach -> diff --git a/src/pane-axis.coffee b/src/pane-axis.coffee index 0a37f1bbb..b69ea3dfb 100644 --- a/src/pane-axis.coffee +++ b/src/pane-axis.coffee @@ -1,5 +1,5 @@ {View} = require './space-pen-extensions' -Pane = null +PaneView = null ### Internal ### module.exports = @@ -25,9 +25,9 @@ class PaneAxis extends View onChildRemoved: (child) => view = @viewForModel(child) view.detach() - Pane ?= require './pane' + PaneView ?= require './pane-view' - if view instanceof Pane and view.model.isDestroyed() + if view instanceof PaneView and view.model.isDestroyed() @getContainer()?.trigger 'pane:removed', [view] getContainer: -> diff --git a/src/pane-container.coffee b/src/pane-container.coffee index 4b258ff7d..a6f90bcba 100644 --- a/src/pane-container.coffee +++ b/src/pane-container.coffee @@ -1,6 +1,6 @@ Serializable = require 'serializable' {$, View} = require './space-pen-extensions' -Pane = require './pane' +PaneView = require './pane-view' PaneContainerModel = require './pane-container-model' # Private: Manages the list of panes within a {WorkspaceView} @@ -47,7 +47,7 @@ class PaneContainer extends View focusedElement = document.activeElement if @hasFocus() oldRoot = @getRoot() - if oldRoot instanceof Pane and oldRoot.model.isDestroyed() + if oldRoot instanceof PaneView and oldRoot.model.isDestroyed() @trigger 'pane:removed', [oldRoot] oldRoot?.detach() if root? @@ -63,7 +63,7 @@ class PaneContainer extends View removeChild: (child) -> throw new Error("Removing non-existant child") unless @getRoot() is child @setRoot(null) - @trigger 'pane:removed', [child] if child instanceof Pane + @trigger 'pane:removed', [child] if child instanceof PaneView saveAll: -> pane.saveItems() for pane in @getPanes() diff --git a/src/pane-model.coffee b/src/pane-model.coffee index 4866e068b..95ba343dd 100644 --- a/src/pane-model.coffee +++ b/src/pane-model.coffee @@ -3,7 +3,7 @@ {Model, Sequence} = require 'theorist' Serializable = require 'serializable' PaneAxisModel = require './pane-axis-model' -Pane = null +PaneView = null # Public: A container for multiple items, one of which is *active* at a given # time. With the default packages, a tab is displayed for each item and the @@ -58,7 +58,7 @@ class PaneModel extends Model params # Private: Called by the view layer to construct a view for this model. - getViewClass: -> Pane ?= require './pane' + getViewClass: -> PaneView ?= require './pane-view' isActive: -> @active diff --git a/src/pane.coffee b/src/pane-view.coffee similarity index 99% rename from src/pane.coffee rename to src/pane-view.coffee index 879e530cc..dbab830b2 100644 --- a/src/pane.coffee +++ b/src/pane-view.coffee @@ -11,7 +11,7 @@ PaneModel = require './pane-model' # Most packages won't need to use this class, unless you're interested in # building a package that deals with switching between panes or tiems. module.exports = -class Pane extends View +class PaneView extends View Serializable.includeInto(this) Delegator.includeInto(this) diff --git a/src/workspace-view.coffee b/src/workspace-view.coffee index cd5075784..5747b7bae 100644 --- a/src/workspace-view.coffee +++ b/src/workspace-view.coffee @@ -6,7 +6,7 @@ _ = require 'underscore-plus' fs = require 'fs-plus' Serializable = require 'serializable' EditorView = require './editor-view' -Pane = require './pane' +PaneView = require './pane-view' PaneColumn = require './pane-column' PaneRow = require './pane-row' PaneContainer = require './pane-container' @@ -39,7 +39,7 @@ Editor = require './editor' module.exports = class WorkspaceView extends View Serializable.includeInto(this) - atom.deserializers.add(this, Pane, PaneRow, PaneColumn, EditorView) + atom.deserializers.add(this, PaneView, PaneRow, PaneColumn, EditorView) @version: 2 @@ -168,7 +168,7 @@ class WorkspaceView extends View Q(editor ? promise) .then (editor) => if not activePane - activePane = new Pane(editor) + activePane = new PaneView(editor) @panes.setRoot(activePane) @itemOpened(editor) @@ -203,7 +203,7 @@ class WorkspaceView extends View pane.activateItem(paneItem) else paneItem = atom.project.openSync(uri, {initialLine}) - pane = new Pane(paneItem) + pane = new PaneView(paneItem) @panes.setRoot(pane) @itemOpened(paneItem) @@ -290,11 +290,11 @@ class WorkspaceView extends View appendToRight: (element) -> @horizontal.append(element) - # Public: Returns the currently focused {Pane}. + # Public: Returns the currently focused {PaneView}. getActivePane: -> @panes.getActivePane() - # Public: Returns the currently focused item from within the focused {Pane} + # Public: Returns the currently focused item from within the focused {PaneView} getActivePaneItem: -> @panes.getActivePaneItem() @@ -329,15 +329,15 @@ class WorkspaceView extends View saveAll: -> @panes.saveAll() - # Public: Fires a callback on each open {Pane}. + # Public: Fires a callback on each open {PaneView}. eachPane: (callback) -> @panes.eachPane(callback) - # Public: Returns an Array of all open {Pane}s. + # Public: Returns an Array of all open {PaneView}s. getPanes: -> @panes.getPanes() - # Public: Return the id of the given a {Pane} + # Public: Return the id of the given a {PaneView} indexOfPane: (pane) -> @panes.indexOfPane(pane) From c7ff4f98976ce09e516a1f7ac901799efe20df47 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 13 Jan 2014 13:33:30 -0700 Subject: [PATCH 2/6] Rename PaneAxis to PaneAxisView --- src/pane-axis-model.coffee | 8 ++++---- src/{pane-axis.coffee => pane-axis-view.coffee} | 2 +- src/{pane-column.coffee => pane-column-view.coffee} | 4 ++-- src/{pane-row.coffee => pane-row-view.coffee} | 4 ++-- src/workspace-view.coffee | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) rename src/{pane-axis.coffee => pane-axis-view.coffee} (97%) rename src/{pane-column.coffee => pane-column-view.coffee} (68%) rename src/{pane-row.coffee => pane-row-view.coffee} (68%) diff --git a/src/pane-axis-model.coffee b/src/pane-axis-model.coffee index bbea4f969..e3e10f5e0 100644 --- a/src/pane-axis-model.coffee +++ b/src/pane-axis-model.coffee @@ -2,8 +2,8 @@ {flatten} = require 'underscore-plus' Serializable = require 'serializable' -PaneRow = null -PaneColumn = null +PaneRowView = null +PaneColumnView = null module.exports = class PaneAxisModel extends Model @@ -34,9 +34,9 @@ class PaneAxisModel extends Model getViewClass: -> if @orientation is 'vertical' - PaneColumn ?= require './pane-column' + PaneColumnView ?= require './pane-column-view' else - PaneRow ?= require './pane-row' + PaneRowView ?= require './pane-row-view' getPanes: -> flatten(@children.map (child) -> child.getPanes()) diff --git a/src/pane-axis.coffee b/src/pane-axis-view.coffee similarity index 97% rename from src/pane-axis.coffee rename to src/pane-axis-view.coffee index b69ea3dfb..f3086cbb1 100644 --- a/src/pane-axis.coffee +++ b/src/pane-axis-view.coffee @@ -3,7 +3,7 @@ PaneView = null ### Internal ### module.exports = -class PaneAxis extends View +class PaneAxisView extends View initialize: (@model) -> @onChildAdded(child) for child in @model.children @subscribe @model.children, 'changed', @onChildrenChanged diff --git a/src/pane-column.coffee b/src/pane-column-view.coffee similarity index 68% rename from src/pane-column.coffee rename to src/pane-column-view.coffee index 4a89e0a6a..ac9d1df6e 100644 --- a/src/pane-column.coffee +++ b/src/pane-column-view.coffee @@ -1,10 +1,10 @@ {$} = require './space-pen-extensions' _ = require 'underscore-plus' -PaneAxis = require './pane-axis' +PaneAxisView = require './pane-axis-view' # Internal: module.exports = -class PaneColumn extends PaneAxis +class PaneColumnView extends PaneAxisView @content: -> @div class: 'pane-column' diff --git a/src/pane-row.coffee b/src/pane-row-view.coffee similarity index 68% rename from src/pane-row.coffee rename to src/pane-row-view.coffee index 76106ab61..8808ce36c 100644 --- a/src/pane-row.coffee +++ b/src/pane-row-view.coffee @@ -1,11 +1,11 @@ {$} = require './space-pen-extensions' _ = require 'underscore-plus' -PaneAxis = require './pane-axis' +PaneAxisView = require './pane-axis-view' ### Internal ### module.exports = -class PaneRow extends PaneAxis +class PaneRowView extends PaneAxisView @content: -> @div class: 'pane-row' diff --git a/src/workspace-view.coffee b/src/workspace-view.coffee index 5747b7bae..815f75d30 100644 --- a/src/workspace-view.coffee +++ b/src/workspace-view.coffee @@ -7,8 +7,8 @@ fs = require 'fs-plus' Serializable = require 'serializable' EditorView = require './editor-view' PaneView = require './pane-view' -PaneColumn = require './pane-column' -PaneRow = require './pane-row' +PaneColumnView = require './pane-column-view' +PaneRowView = require './pane-row-view' PaneContainer = require './pane-container' Editor = require './editor' @@ -39,7 +39,7 @@ Editor = require './editor' module.exports = class WorkspaceView extends View Serializable.includeInto(this) - atom.deserializers.add(this, PaneView, PaneRow, PaneColumn, EditorView) + atom.deserializers.add(this, PaneView, PaneRowView, PaneColumnView, EditorView) @version: 2 From 918c31905f57bc626d47e97ce570c7857acedf43 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 13 Jan 2014 13:39:02 -0700 Subject: [PATCH 3/6] Rename PaneContainer to PaneContainerView --- ...tainer-spec.coffee => pane-container-view-spec.coffee} | 8 ++++---- spec/pane-view-spec.coffee | 4 ++-- src/{pane-container.coffee => pane-container-view.coffee} | 2 +- src/workspace-view.coffee | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) rename spec/{pane-container-spec.coffee => pane-container-view-spec.coffee} (98%) rename src/{pane-container.coffee => pane-container-view.coffee} (98%) diff --git a/spec/pane-container-spec.coffee b/spec/pane-container-view-spec.coffee similarity index 98% rename from spec/pane-container-spec.coffee rename to spec/pane-container-view-spec.coffee index b2a861196..fa0bcb83d 100644 --- a/spec/pane-container-spec.coffee +++ b/spec/pane-container-view-spec.coffee @@ -1,10 +1,10 @@ path = require 'path' temp = require 'temp' -PaneContainer = require '../src/pane-container' +PaneContainerView = require '../src/pane-container-view' PaneView = require '../src/pane-view' {_, $, View, $$} = require 'atom' -describe "PaneContainer", -> +describe "PaneContainerView", -> [TestView, container, pane1, pane2, pane3] = [] beforeEach -> @@ -18,7 +18,7 @@ describe "PaneContainer", -> save: -> @saved = true isEqual: (other) -> @name is other?.name - container = new PaneContainer + container = new PaneContainerView pane1 = new PaneView(new TestView('1')) container.setRoot(pane1) pane2 = pane1.splitRight(new TestView('2')) @@ -146,7 +146,7 @@ describe "PaneContainer", -> item2b = new TestView('2b') item3a = new TestView('3a') - container = new PaneContainer + container = new PaneContainerView container.attachToDom() pane1 = new PaneView(item1a) container.setRoot(pane1) diff --git a/spec/pane-view-spec.coffee b/spec/pane-view-spec.coffee index d609d501a..7440f7e73 100644 --- a/spec/pane-view-spec.coffee +++ b/spec/pane-view-spec.coffee @@ -1,4 +1,4 @@ -PaneContainer = require '../src/pane-container' +PaneContainerView = require '../src/pane-container-view' PaneView = require '../src/pane-view' {fs, $, View} = require 'atom' path = require 'path' @@ -17,7 +17,7 @@ describe "PaneView", -> beforeEach -> atom.deserializers.add(TestView) - container = new PaneContainer + container = new PaneContainerView view1 = new TestView(id: 'view-1', text: 'View 1') view2 = new TestView(id: 'view-2', text: 'View 2') editor1 = atom.project.openSync('sample.js') diff --git a/src/pane-container.coffee b/src/pane-container-view.coffee similarity index 98% rename from src/pane-container.coffee rename to src/pane-container-view.coffee index a6f90bcba..d61edf736 100644 --- a/src/pane-container.coffee +++ b/src/pane-container-view.coffee @@ -5,7 +5,7 @@ PaneContainerModel = require './pane-container-model' # Private: Manages the list of panes within a {WorkspaceView} module.exports = -class PaneContainer extends View +class PaneContainerView extends View atom.deserializers.add(this) Serializable.includeInto(this) diff --git a/src/workspace-view.coffee b/src/workspace-view.coffee index 815f75d30..b5bdff230 100644 --- a/src/workspace-view.coffee +++ b/src/workspace-view.coffee @@ -9,7 +9,7 @@ EditorView = require './editor-view' PaneView = require './pane-view' PaneColumnView = require './pane-column-view' PaneRowView = require './pane-row-view' -PaneContainer = require './pane-container' +PaneContainerView = require './pane-container-view' Editor = require './editor' # Public: The container for the entire Atom application. @@ -60,7 +60,7 @@ class WorkspaceView extends View # Private: initialize: ({panes, @fullScreen}={}) -> - panes ?= new PaneContainer + panes ?= new PaneContainerView @panes.replaceWith(panes) @panes = panes From 8931bf8f3a5ac2e30ff6b6f60c2b20ed3e424553 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 13 Jan 2014 13:51:15 -0700 Subject: [PATCH 4/6] Rename PaneModel to Pane --- spec/pane-container-model-spec.coffee | 8 +- spec/pane-model-spec.coffee | 12 +- src/pane-container-model.coffee | 4 +- src/pane-view.coffee | 10 +- src/pane.coffee | 307 ++++++++++++++++++++++++++ 5 files changed, 324 insertions(+), 17 deletions(-) create mode 100644 src/pane.coffee diff --git a/spec/pane-container-model-spec.coffee b/spec/pane-container-model-spec.coffee index 027272218..7f1fff2d3 100644 --- a/spec/pane-container-model-spec.coffee +++ b/spec/pane-container-model-spec.coffee @@ -1,5 +1,5 @@ PaneContainerModel = require '../src/pane-container-model' -PaneModel = require '../src/pane-model' +Pane = require '../src/pane' describe "PaneContainerModel", -> describe "serialization", -> @@ -12,7 +12,7 @@ describe "PaneContainerModel", -> @deserialize: -> new this serialize: -> deserializer: 'Item' - pane1A = new PaneModel(items: [new Item]) + pane1A = new Pane(items: [new Item]) containerA = new PaneContainerModel(root: pane1A) pane2A = pane1A.splitRight(items: [new Item]) pane3A = pane2A.splitDown(items: [new Item]) @@ -36,7 +36,7 @@ describe "PaneContainerModel", -> [container, pane1, pane2] = [] beforeEach -> - pane1 = new PaneModel + pane1 = new Pane container = new PaneContainerModel(root: pane1) it "references the first pane if no pane has been made active", -> @@ -67,7 +67,7 @@ describe "PaneContainerModel", -> [container, pane, surrenderedFocusHandler] = [] beforeEach -> - pane = new PaneModel + pane = new Pane container = new PaneContainerModel(root: pane) container.on 'surrendered-focus', surrenderedFocusHandler = jasmine.createSpy("surrenderedFocusHandler") diff --git a/spec/pane-model-spec.coffee b/spec/pane-model-spec.coffee index 6eb897b06..bb7d6e7eb 100644 --- a/spec/pane-model-spec.coffee +++ b/spec/pane-model-spec.coffee @@ -1,14 +1,14 @@ {Model} = require 'theorist' -PaneModel = require '../src/pane-model' +Pane = require '../src/pane' PaneAxisModel = require '../src/pane-axis-model' PaneContainerModel = require '../src/pane-container-model' -describe "PaneModel", -> +describe "Pane", -> describe "split methods", -> [pane1, container] = [] beforeEach -> - pane1 = new PaneModel(items: ["A"]) + pane1 = new Pane(items: ["A"]) container = new PaneContainerModel(root: pane1) describe "::splitLeft(params)", -> @@ -87,14 +87,14 @@ describe "PaneModel", -> describe "::destroyItem(item)", -> describe "when the last item is destroyed", -> it "destroys the pane", -> - pane = new PaneModel(items: ["A", "B"]) + pane = new Pane(items: ["A", "B"]) pane.destroyItem("A") pane.destroyItem("B") expect(pane.isDestroyed()).toBe true describe "when an item emits a destroyed event", -> it "removes it from the list of items", -> - pane = new PaneModel(items: [new Model, new Model, new Model]) + pane = new Pane(items: [new Model, new Model, new Model]) [item1, item2, item3] = pane.items pane.items[1].destroy() expect(pane.items).toEqual [item1, item3] @@ -103,7 +103,7 @@ describe "PaneModel", -> [pane1, container] = [] beforeEach -> - pane1 = new PaneModel(items: [new Model, new Model]) + pane1 = new Pane(items: [new Model, new Model]) container = new PaneContainerModel(root: pane1) it "destroys the pane's destroyable items", -> diff --git a/src/pane-container-model.coffee b/src/pane-container-model.coffee index f7fa4c0c6..eb69a12f7 100644 --- a/src/pane-container-model.coffee +++ b/src/pane-container-model.coffee @@ -1,6 +1,6 @@ {Model} = require 'theorist' Serializable = require 'serializable' -PaneModel = require './pane-model' +Pane = require './pane' module.exports = class PaneContainerModel extends Model @@ -56,7 +56,7 @@ class PaneContainerModel extends Model root.parent = this root.container = this - if root instanceof PaneModel + if root instanceof Pane @activePane ?= root @subscribe root, 'destroyed', => @activePane = null diff --git a/src/pane-view.coffee b/src/pane-view.coffee index dbab830b2..fe9da3f31 100644 --- a/src/pane-view.coffee +++ b/src/pane-view.coffee @@ -2,7 +2,7 @@ Serializable = require 'serializable' Delegator = require 'delegato' -PaneModel = require './pane-model' +Pane = require './pane' # Public: A container which can contains multiple items to be switched between. # @@ -18,7 +18,7 @@ class PaneView extends View @version: 1 @deserialize: (state) -> - new this(PaneModel.deserialize(state.model)) + new this(Pane.deserialize(state.model)) @content: (wrappedView) -> @div class: 'pane', tabindex: -1, => @@ -36,10 +36,10 @@ class PaneView extends View # Private: initialize: (args...) -> - if args[0] instanceof PaneModel + if args[0] instanceof Pane @model = args[0] else - @model = new PaneModel(items: args) + @model = new Pane(items: args) @model._view = this @onItemAdded(item) for item in @items @@ -86,7 +86,7 @@ class PaneView extends View @command 'pane:close-other-items', => @destroyInactiveItems() deserializeParams: (params) -> - params.model = PaneModel.deserialize(params.model) + params.model = Pane.deserialize(params.model) params serializeParams: -> diff --git a/src/pane.coffee b/src/pane.coffee new file mode 100644 index 000000000..380c6506f --- /dev/null +++ b/src/pane.coffee @@ -0,0 +1,307 @@ +{find, compact, extend} = require 'underscore-plus' +{dirname} = require 'path' +{Model, Sequence} = require 'theorist' +Serializable = require 'serializable' +PaneAxisModel = require './pane-axis-model' +PaneView = null + +# Public: A container for multiple items, one of which is *active* at a given +# time. With the default packages, a tab is displayed for each item and the +# active item's view is displayed. +module.exports = +class Pane extends Model + atom.deserializers.add(this) + Serializable.includeInto(this) + + @properties + container: null + activeItem: null + focused: false + + # Public: Only one pane is considered *active* at a time. A pane is activated + # when it is focused, and when focus returns to the pane container after + # moving to another element such as a panel, it returns to the active pane. + @behavior 'active', -> + @$container + .switch((container) -> container?.$activePane) + .map((activePane) => activePane is this) + .distinctUntilChanged() + + # Private: + constructor: (params) -> + super + + @items = Sequence.fromArray(params?.items ? []) + @activeItem ?= @items[0] + + @subscribe @items.onEach (item) => + if typeof item.on is 'function' + @subscribe item, 'destroyed', => @removeItem(item) + + @subscribe @items.onRemoval (item, index) => + @unsubscribe item if typeof item.on is 'function' + + @activate() if params?.active + + # Private: Called by the Serializable mixin during serialization. + serializeParams: -> + items: compact(@items.map((item) -> item.serialize?())) + activeItemUri: @activeItem?.getUri?() + focused: @focused + active: @active + + # Private: Called by the Serializable mixin during deserialization. + deserializeParams: (params) -> + {items, activeItemUri} = params + params.items = compact(items.map (itemState) -> atom.deserializers.deserialize(itemState)) + params.activeItem = find params.items, (item) -> item.getUri?() is activeItemUri + params + + # Private: Called by the view layer to construct a view for this model. + getViewClass: -> PaneView ?= require './pane-view' + + isActive: -> @active + + # Private: Called by the view layer to indicate that the pane has gained focus. + focus: -> + @focused = true + @activate() unless @isActive() + + # Private: Called by the view layer to indicate that the pane has lost focus. + blur: -> + @focused = false + true # if this is called from an event handler, don't cancel it + + # Public: Makes this pane the *active* pane, causing it to gain focus + # immediately. + activate: -> + @container?.activePane = this + @emit 'activated' + + # Private: + getPanes: -> [this] + + # Public: + getItems: -> + @items.slice() + + # Public: Returns the item at the specified index. + itemAtIndex: (index) -> + @items[index] + + # Public: Makes the next item active. + activateNextItem: -> + index = @getActiveItemIndex() + if index < @items.length - 1 + @activateItemAtIndex(index + 1) + else + @activateItemAtIndex(0) + + # Public: Makes the previous item active. + activatePreviousItem: -> + index = @getActiveItemIndex() + if index > 0 + @activateItemAtIndex(index - 1) + else + @activateItemAtIndex(@items.length - 1) + + # Public: Returns the index of the current active item. + getActiveItemIndex: -> + @items.indexOf(@activeItem) + + # Public: Makes the item at the given index active. + activateItemAtIndex: (index) -> + @activateItem(@itemAtIndex(index)) + + # Public: Makes the given item active, adding the item if necessary. + activateItem: (item) -> + if item? + @addItem(item) + @activeItem = item + + # Public: Adds the item to the pane. + # + # * item: + # The item to add. It can be a model with an associated view or a view. + # * index: + # An optional index at which to add the item. If omitted, the item is + # added to the end. + # + # Returns the added item + addItem: (item, index=@getActiveItemIndex() + 1) -> + return if item in @items + + @items.splice(index, 0, item) + @emit 'item-added', item, index + item + + # Private: + removeItem: (item, destroying) -> + index = @items.indexOf(item) + return if index is -1 + @activateNextItem() if item is @activeItem and @items.length > 1 + @items.splice(index, 1) + @emit 'item-removed', item, index, destroying + @destroy() if @items.length is 0 + + # Public: Moves the given item to the specified index. + moveItem: (item, newIndex) -> + oldIndex = @items.indexOf(item) + @items.splice(oldIndex, 1) + @items.splice(newIndex, 0, item) + @emit 'item-moved', item, newIndex + + # Public: Moves the given item to the given index at another pane. + moveItemToPane: (item, pane, index) -> + pane.addItem(item, index) + @removeItem(item) + + # Public: Destroys the currently active item and make the next item active. + destroyActiveItem: -> + @destroyItem(@activeItem) + false + + # Public: Destroys the given item. If it is the active item, activate the next + # one. If this is the last item, also destroys the pane. + destroyItem: (item) -> + @emit 'before-item-destroyed', item + if @promptToSaveItem(item) + @emit 'item-destroyed', item + @removeItem(item, true) + item.destroy?() + true + else + false + + # Public: Destroys all items and destroys the pane. + destroyItems: -> + @destroyItem(item) for item in @getItems() + + # Public: Destroys all items but the active one. + destroyInactiveItems: -> + @destroyItem(item) for item in @getItems() when item isnt @activeItem + + # Private: Called by model superclass. + destroyed: -> + @container.activateNextPane() if @isActive() + item.destroy?() for item in @items.slice() + + # Public: Prompts the user to save the given item if it can be saved and is + # currently unsaved. + promptToSaveItem: (item) -> + return true unless item.shouldPromptToSave?() + + uri = item.getUri() + chosen = atom.confirm + message: "'#{item.getTitle?() ? item.getUri()}' has changes, do you want to save them?" + detailedMessage: "Your changes will be lost if you close this item without saving." + buttons: ["Save", "Cancel", "Don't Save"] + + switch chosen + when 0 then @saveItem(item, -> true) + when 1 then false + when 2 then true + + # Public: Saves the active item. + saveActiveItem: -> + @saveItem(@activeItem) + + # Public: Saves the active item at a prompted-for location. + saveActiveItemAs: -> + @saveItemAs(@activeItem) + + # Public: Saves the specified item. + # + # * item: The item to save. + # * nextAction: An optional function which will be called after the item is saved. + saveItem: (item, nextAction) -> + if item.getUri?() + item.save?() + nextAction?() + else + @saveItemAs(item, nextAction) + + # Public: Saves the given item at a prompted-for location. + # + # * item: The item to save. + # * nextAction: An optional function which will be called after the item is saved. + saveItemAs: (item, nextAction) -> + return unless item.saveAs? + + itemPath = item.getPath?() + itemPath = dirname(itemPath) if itemPath + path = atom.showSaveDialogSync(itemPath) + if path + item.saveAs(path) + nextAction?() + + # Public: Saves all items. + saveItems: -> + @saveItem(item) for item in @getItems() + + # Public: Returns the first item that matches the given URI or undefined if + # none exists. + itemForUri: (uri) -> + find @items, (item) -> item.getUri?() is uri + + # Public: Activates the first item that matches the given URI. Returns a + # boolean indicating whether a matching item was found. + activateItemForUri: (uri) -> + if item = @itemForUri(uri) + @activateItem(item) + true + else + false + + # Private: + copyActiveItem: -> + @activeItem.copy?() ? atom.deserializers.deserialize(@activeItem.serialize()) + + # Public: Creates a new pane to the left of the receiver. + # + # * params: + # + items: An optional array of items with which to construct the new pane. + # + # Returns the new {Pane}. + splitLeft: (params) -> + @split('horizontal', 'before', params) + + # Public: Creates a new pane to the right of the receiver. + # + # * params: + # + items: An optional array of items with which to construct the new pane. + # + # Returns the new {Pane}. + splitRight: (params) -> + @split('horizontal', 'after', params) + + # Public: Creates a new pane above the receiver. + # + # * params: + # + items: An optional array of items with which to construct the new pane. + # + # Returns the new {Pane}. + splitUp: (params) -> + @split('vertical', 'before', params) + + # Public: Creates a new pane below the receiver. + # + # * params: + # + items: An optional array of items with which to construct the new pane. + # + # Returns the new {Pane}. + splitDown: (params) -> + @split('vertical', 'after', params) + + # Private: + split: (orientation, side, params) -> + if @parent.orientation isnt orientation + @parent.replaceChild(this, new PaneAxisModel({@container, orientation, children: [this]})) + + newPane = new @constructor(extend({focused: true}, params)) + switch side + when 'before' then @parent.insertChildBefore(this, newPane) + when 'after' then @parent.insertChildAfter(this, newPane) + + newPane.activate() + newPane From a268b3e9637e79df59a90dd00b54b96011b54301 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 13 Jan 2014 13:54:04 -0700 Subject: [PATCH 5/6] Rename PaneAxisModel to PaneAxis --- spec/pane-model-spec.coffee | 2 +- src/{pane-axis-model.coffee => pane-axis.coffee} | 2 +- src/pane-model.coffee | 4 ++-- src/pane.coffee | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) rename src/{pane-axis-model.coffee => pane-axis.coffee} (98%) diff --git a/spec/pane-model-spec.coffee b/spec/pane-model-spec.coffee index bb7d6e7eb..38d4beb91 100644 --- a/spec/pane-model-spec.coffee +++ b/spec/pane-model-spec.coffee @@ -1,6 +1,6 @@ {Model} = require 'theorist' Pane = require '../src/pane' -PaneAxisModel = require '../src/pane-axis-model' +PaneAxis = require '../src/pane-axis' PaneContainerModel = require '../src/pane-container-model' describe "Pane", -> diff --git a/src/pane-axis-model.coffee b/src/pane-axis.coffee similarity index 98% rename from src/pane-axis-model.coffee rename to src/pane-axis.coffee index e3e10f5e0..39657fcf7 100644 --- a/src/pane-axis-model.coffee +++ b/src/pane-axis.coffee @@ -6,7 +6,7 @@ PaneRowView = null PaneColumnView = null module.exports = -class PaneAxisModel extends Model +class PaneAxis extends Model atom.deserializers.add(this) Serializable.includeInto(this) diff --git a/src/pane-model.coffee b/src/pane-model.coffee index 95ba343dd..a6902968a 100644 --- a/src/pane-model.coffee +++ b/src/pane-model.coffee @@ -2,7 +2,7 @@ {dirname} = require 'path' {Model, Sequence} = require 'theorist' Serializable = require 'serializable' -PaneAxisModel = require './pane-axis-model' +PaneAxis = require './pane-axis' PaneView = null # Public: A container for multiple items, one of which is *active* at a given @@ -296,7 +296,7 @@ class PaneModel extends Model # Private: split: (orientation, side, params) -> if @parent.orientation isnt orientation - @parent.replaceChild(this, new PaneAxisModel({@container, orientation, children: [this]})) + @parent.replaceChild(this, new PaneAxis({@container, orientation, children: [this]})) newPane = new @constructor(extend({focused: true}, params)) switch side diff --git a/src/pane.coffee b/src/pane.coffee index 380c6506f..746cfb989 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -2,7 +2,7 @@ {dirname} = require 'path' {Model, Sequence} = require 'theorist' Serializable = require 'serializable' -PaneAxisModel = require './pane-axis-model' +PaneAxis = require './pane-axis' PaneView = null # Public: A container for multiple items, one of which is *active* at a given @@ -296,7 +296,7 @@ class Pane extends Model # Private: split: (orientation, side, params) -> if @parent.orientation isnt orientation - @parent.replaceChild(this, new PaneAxisModel({@container, orientation, children: [this]})) + @parent.replaceChild(this, new PaneAxis({@container, orientation, children: [this]})) newPane = new @constructor(extend({focused: true}, params)) switch side From 97999f10806da724b8ce90beb48de1915a591803 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 13 Jan 2014 13:56:31 -0700 Subject: [PATCH 6/6] Rename PaneContainerModel to PaneContainer --- spec/pane-container-model-spec.coffee | 10 +++++----- spec/pane-model-spec.coffee | 6 +++--- src/pane-container-view.coffee | 8 ++++---- ...ne-container-model.coffee => pane-container.coffee} | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) rename src/{pane-container-model.coffee => pane-container.coffee} (97%) diff --git a/spec/pane-container-model-spec.coffee b/spec/pane-container-model-spec.coffee index 7f1fff2d3..759b4d7b5 100644 --- a/spec/pane-container-model-spec.coffee +++ b/spec/pane-container-model-spec.coffee @@ -1,7 +1,7 @@ -PaneContainerModel = require '../src/pane-container-model' +PaneContainer = require '../src/pane-container' Pane = require '../src/pane' -describe "PaneContainerModel", -> +describe "PaneContainer", -> describe "serialization", -> [containerA, pane1A, pane2A, pane3A] = [] @@ -13,7 +13,7 @@ describe "PaneContainerModel", -> serialize: -> deserializer: 'Item' pane1A = new Pane(items: [new Item]) - containerA = new PaneContainerModel(root: pane1A) + containerA = new PaneContainer(root: pane1A) pane2A = pane1A.splitRight(items: [new Item]) pane3A = pane2A.splitDown(items: [new Item]) @@ -37,7 +37,7 @@ describe "PaneContainerModel", -> beforeEach -> pane1 = new Pane - container = new PaneContainerModel(root: pane1) + container = new PaneContainer(root: pane1) it "references the first pane if no pane has been made active", -> expect(container.activePane).toBe pane1 @@ -68,7 +68,7 @@ describe "PaneContainerModel", -> beforeEach -> pane = new Pane - container = new PaneContainerModel(root: pane) + container = new PaneContainer(root: pane) container.on 'surrendered-focus', surrenderedFocusHandler = jasmine.createSpy("surrenderedFocusHandler") it "assigns null to the root and the activePane", -> diff --git a/spec/pane-model-spec.coffee b/spec/pane-model-spec.coffee index 38d4beb91..0c15683a4 100644 --- a/spec/pane-model-spec.coffee +++ b/spec/pane-model-spec.coffee @@ -1,7 +1,7 @@ {Model} = require 'theorist' Pane = require '../src/pane' PaneAxis = require '../src/pane-axis' -PaneContainerModel = require '../src/pane-container-model' +PaneContainer = require '../src/pane-container' describe "Pane", -> describe "split methods", -> @@ -9,7 +9,7 @@ describe "Pane", -> beforeEach -> pane1 = new Pane(items: ["A"]) - container = new PaneContainerModel(root: pane1) + container = new PaneContainer(root: pane1) describe "::splitLeft(params)", -> describe "when the parent is the container root", -> @@ -104,7 +104,7 @@ describe "Pane", -> beforeEach -> pane1 = new Pane(items: [new Model, new Model]) - container = new PaneContainerModel(root: pane1) + container = new PaneContainer(root: pane1) it "destroys the pane's destroyable items", -> [item1, item2] = pane1.items diff --git a/src/pane-container-view.coffee b/src/pane-container-view.coffee index d61edf736..a55a1d65b 100644 --- a/src/pane-container-view.coffee +++ b/src/pane-container-view.coffee @@ -1,7 +1,7 @@ Serializable = require 'serializable' {$, View} = require './space-pen-extensions' PaneView = require './pane-view' -PaneContainerModel = require './pane-container-model' +PaneContainer = require './pane-container' # Private: Manages the list of panes within a {WorkspaceView} module.exports = @@ -10,16 +10,16 @@ class PaneContainerView extends View Serializable.includeInto(this) @deserialize: (state) -> - new this(PaneContainerModel.deserialize(state.model)) + new this(PaneContainer.deserialize(state.model)) @content: -> @div class: 'panes' initialize: (params) -> - if params instanceof PaneContainerModel + if params instanceof PaneContainer @model = params else - @model = new PaneContainerModel({root: params?.root?.model}) + @model = new PaneContainer({root: params?.root?.model}) @subscribe @model.$root, @onRootChanged @subscribe @model.$activePaneItem.changes, @onActivePaneItemChanged diff --git a/src/pane-container-model.coffee b/src/pane-container.coffee similarity index 97% rename from src/pane-container-model.coffee rename to src/pane-container.coffee index eb69a12f7..14803afc8 100644 --- a/src/pane-container-model.coffee +++ b/src/pane-container.coffee @@ -3,7 +3,7 @@ Serializable = require 'serializable' Pane = require './pane' module.exports = -class PaneContainerModel extends Model +class PaneContainer extends Model atom.deserializers.add(this) Serializable.includeInto(this)