diff --git a/spec/pane-container-spec.coffee b/spec/pane-container-spec.coffee index cb6405f73..dd6aa24a5 100644 --- a/spec/pane-container-spec.coffee +++ b/spec/pane-container-spec.coffee @@ -205,3 +205,132 @@ describe "PaneContainer", -> newContainer = deserialize(container.serialize()) expect(newContainer.find('.row, .column')).not.toExist() expect(newContainer.find('> :contains(1)')).toExist() + + describe "pane-container:active-item-changed", -> + [pane1, item1a, item1b, item2a, item2b, item3a, container, activeItemChangedHandler] = [] + beforeEach -> + item1a = new TestView('1a') + item1b = new TestView('1b') + item2a = new TestView('2a') + item2b = new TestView('2b') + item3a = new TestView('3a') + + container = new PaneContainer + container.attachToDom() + pane1 = new Pane(item1a) + container.setRoot(pane1) + + activeItemChangedHandler = jasmine.createSpy("activeItemChangedHandler") + container.on 'pane-container:active-item-changed', activeItemChangedHandler + + describe "when there are no panes", -> + it "is triggered when a new pane item is added", -> + container.setRoot() + expect(container.getPanes().length).toBe 0 + activeItemChangedHandler.reset() + + pane = new Pane(item1a) + container.setRoot(pane) + expect(activeItemChangedHandler.callCount).toBe 1 + expect(activeItemChangedHandler.argsForCall[0][1]).toEqual item1a + + describe "when there is one pane", -> + it "is triggered when a new pane item is added", -> + pane1.showItem(item1b) + expect(activeItemChangedHandler.callCount).toBe 1 + expect(activeItemChangedHandler.argsForCall[0][1]).toEqual item1b + + it "is not triggered when the active pane item is shown again", -> + pane1.showItem(item1a) + expect(activeItemChangedHandler).not.toHaveBeenCalled() + + it "is triggered when switching to an existing pane item", -> + pane1.showItem(item1b) + activeItemChangedHandler.reset() + + pane1.showItem(item1a) + expect(activeItemChangedHandler.callCount).toBe 1 + expect(activeItemChangedHandler.argsForCall[0][1]).toEqual item1a + + it "is triggered when the active pane item is removed", -> + pane1.showItem(item1b) + activeItemChangedHandler.reset() + + pane1.removeItem(item1b) + expect(activeItemChangedHandler.callCount).toBe 1 + expect(activeItemChangedHandler.argsForCall[0][1]).toEqual item1a + + it "is not triggered when an inactive pane item is removed", -> + pane1.showItem(item1b) + activeItemChangedHandler.reset() + + pane1.removeItem(item1a) + expect(activeItemChangedHandler).not.toHaveBeenCalled() + + it "is triggered when all pane items are removed", -> + pane1.removeItem(item1a) + expect(activeItemChangedHandler.callCount).toBe 1 + expect(activeItemChangedHandler.argsForCall[0][1]).toBe undefined + + it "is triggered when the pane is removed", -> + pane1.remove() + expect(activeItemChangedHandler.callCount).toBe 1 + expect(activeItemChangedHandler.argsForCall[0][1]).toBe undefined + + describe "when there are two panes", -> + [pane2] = [] + + beforeEach -> + pane2 = pane1.splitLeft(item2a) + activeItemChangedHandler.reset() + + it "is triggered when a new pane item is added to the active pane", -> + pane2.showItem(item2b) + expect(activeItemChangedHandler.callCount).toBe 1 + expect(activeItemChangedHandler.argsForCall[0][1]).toEqual item2b + + it "is not triggered when a new pane item is added to an inactive pane", -> + pane1.showItem(item1b) + expect(activeItemChangedHandler).not.toHaveBeenCalled() + + it "is triggered when the active pane item removed from the active pane", -> + pane2.showItem(item2b) + activeItemChangedHandler.reset() + + pane2.removeItem(item2b) + expect(activeItemChangedHandler.callCount).toBe 1 + expect(activeItemChangedHandler.argsForCall[0][1]).toEqual item2a + + it "is not triggered when the active pane item removed from an inactive pane", -> + pane1.showItem(item1b) + activeItemChangedHandler.reset() + + pane1.removeItem(item1b) + expect(activeItemChangedHandler).not.toHaveBeenCalled() + + it "is triggered when the active pane is removed", -> + pane2.remove() + expect(activeItemChangedHandler.callCount).toBe 1 + expect(activeItemChangedHandler.argsForCall[0][1]).toEqual item1a + + it "is not triggered when an inactive pane is removed", -> + pane1.remove() + expect(activeItemChangedHandler).not.toHaveBeenCalled() + + describe "when there are multiple panes", -> + beforeEach -> + pane2 = pane1.splitRight(item2a) + activeItemChangedHandler.reset() + + it "is triggered when a new pane is added", -> + pane2.splitDown(item3a) + expect(activeItemChangedHandler.callCount).toBe 1 + expect(activeItemChangedHandler.argsForCall[0][1]).toEqual item3a + + it "is not triggered when the non active pane is removed", -> + pane3 = pane2.splitDown(item3a) + activeItemChangedHandler.reset() + + pane1.remove() + pane2.remove() + expect(activeItemChangedHandler).not.toHaveBeenCalled() diff --git a/src/pane-axis.coffee b/src/pane-axis.coffee index adb2b3657..d95cb976c 100644 --- a/src/pane-axis.coffee +++ b/src/pane-axis.coffee @@ -35,6 +35,7 @@ class PaneAxis extends View parent = @parent().view() container = @getContainer() + childWasInactive = not child.isActive?() primitiveRemove = (child) => node = child[0] @@ -48,8 +49,9 @@ class PaneAxis extends View sibling = @children().view() siblingFocused = sibling.is(':has(:focus)') sibling.detach() + if parent.setRoot? - parent.setRoot(sibling, options) + parent.setRoot(sibling, suppressPaneItemChangeEvents: childWasInactive) else parent.insertChildBefore(this, sibling, options) parent.removeChild(this, options) diff --git a/src/pane-container.coffee b/src/pane-container.coffee index 18e819c01..ac9821162 100644 --- a/src/pane-container.coffee +++ b/src/pane-container.coffee @@ -92,14 +92,18 @@ class PaneContainer extends View @destroyedItemStates = @destroyedItemStates.filter (itemState) -> itemState.uri isnt itemUri + triggerActiveItemChange: (item) -> + @trigger 'pane-container:active-item-changed', [item] + getRoot: -> @children().first().view() - setRoot: (root) -> + setRoot: (root, {suppressPaneItemChangeEvents}={}) -> @empty() if root? @append(root) @itemAdded(root.activeItem) if root.activeItem + @triggerActiveItemChange(root?.getActivePaneItem()) unless suppressPaneItemChangeEvents @state.set(root: root?.getState()) removeChild: (child) -> diff --git a/src/pane.coffee b/src/pane.coffee index afbdc5801..2523fc762 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -113,7 +113,7 @@ class Pane extends View # Public: Returns whether this pane is currently focused. isActive: -> - @hasClass('active') + @getContainer()?.getActivePane() == this # Public: Returns the next pane, ordered by creation. getNextPane: -> @@ -175,6 +175,7 @@ class Pane extends View view.focus() if isFocused @activeItem = item @activeView = view + @getContainer()?.triggerActiveItemChange(item) if @isActive() @trigger 'pane:active-item-changed', [item] @state.set('activeItemUri', item.getUri?()) @@ -425,6 +426,7 @@ class Pane extends View when 'after' then parent.insertChildAfter(this, newPane) @getContainer().adjustPaneDimensions() newPane.focus() + @getContainer().triggerActiveItemChange(newPane.getActivePaneItem()) newPane # Private: