Merge pull request #9029 from ssorallen/stop-changing-active-pane

Add `onDidStopChangingActivePaneItem` for async callbacks
This commit is contained in:
Nathan Sobo
2015-10-12 12:19:37 -06:00
3 changed files with 66 additions and 1 deletions

View File

@@ -122,6 +122,29 @@ describe "PaneContainer", ->
pane2.activate()
expect(observed).toEqual [pane1.itemAtIndex(0), pane2.itemAtIndex(0)]
describe "::onDidStopChangingActivePaneItem()", ->
[container, pane1, pane2, observed] = []
beforeEach ->
container = new PaneContainer(root: new Pane(items: [new Object, new Object]))
container.getRoot().splitRight(items: [new Object, new Object])
[pane1, pane2] = container.getPanes()
observed = []
container.onDidStopChangingActivePaneItem (item) -> observed.push(item)
it "invokes observers when the active item of the active pane stops changing", ->
pane2.activateNextItem()
pane2.activateNextItem()
advanceClock(100)
expect(observed).toEqual [pane2.itemAtIndex(0)]
it "invokes observers when the active pane stops changing", ->
pane1.activate()
pane2.activate()
advanceClock(100)
expect(observed).toEqual [pane2.itemAtIndex(0)]
describe "::observePanes()", ->
it "invokes observers with all current and future panes", ->
container = new PaneContainer

View File

@@ -12,6 +12,8 @@ class PaneContainer extends Model
@version: 1
root: null
stoppedChangingActivePaneItemDelay: 100
stoppedChangingActivePaneItemTimeout: null
@deserialize: (state) ->
container = Object.create(@prototype) # allows us to pass a self reference to our child before invoking constructor
@@ -82,6 +84,9 @@ class PaneContainer extends Model
onDidChangeActivePaneItem: (fn) ->
@emitter.on 'did-change-active-pane-item', fn
onDidStopChangingActivePaneItem: (fn) ->
@emitter.on 'did-stop-changing-active-pane-item', fn
observeActivePaneItem: (fn) ->
fn(@getActivePaneItem())
@onDidChangeActivePaneItem(fn)
@@ -189,12 +194,18 @@ class PaneContainer extends Model
# Called by Model superclass when destroyed
destroyed: ->
@cancelStoppedChangingActivePaneItemTimeout()
pane.destroy() for pane in @getPanes()
@subscriptions.dispose()
@emitter.dispose()
cancelStoppedChangingActivePaneItemTimeout: ->
if @stoppedChangingActivePaneItemTimeout?
clearTimeout(@stoppedChangingActivePaneItemTimeout)
monitorActivePaneItem: ->
childSubscription = null
@subscriptions.add @observeActivePane (activePane) =>
if childSubscription?
@subscriptions.remove(childSubscription)
@@ -202,6 +213,14 @@ class PaneContainer extends Model
childSubscription = activePane.observeActiveItem (activeItem) =>
@emitter.emit 'did-change-active-pane-item', activeItem
@cancelStoppedChangingActivePaneItemTimeout()
stoppedChangingActivePaneItemCallback = =>
@stoppedChangingActivePaneItemTimeout = null
@emitter.emit 'did-stop-changing-active-pane-item', activeItem
@stoppedChangingActivePaneItemTimeout =
setTimeout(
stoppedChangingActivePaneItemCallback,
@stoppedChangingActivePaneItemDelay)
@subscriptions.add(childSubscription)

View File

@@ -209,11 +209,34 @@ class Workspace extends Model
# Essential: Invoke the given callback when the active pane item changes.
#
# Because observers are invoked synchronously, it's important not to perform
# any expensive operations via this method. Consider
# {::onDidStopChangingActivePaneItem} to delay operations until after changes
# stop occurring.
#
# * `callback` {Function} to be called when the active pane item changes.
# * `item` The active pane item.
#
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
onDidChangeActivePaneItem: (callback) -> @paneContainer.onDidChangeActivePaneItem(callback)
onDidChangeActivePaneItem: (callback) ->
@paneContainer.onDidChangeActivePaneItem(callback)
# Essential: Invoke the given callback when the active pane item stops
# changing.
#
# Observers are called asynchronously 100ms after the last active pane item
# change. Handling changes here rather than in the synchronous
# {::onDidChangeActivePaneItem} prevents unneeded work if the user is quickly
# changing or closing tabs and ensures critical UI feedback, like changing the
# highlighted tab, gets priority over work that can be done asynchronously.
#
# * `callback` {Function} to be called when the active pane item stopts
# changing.
# * `item` The active pane item.
#
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
onDidStopChangingActivePaneItem: (callback) ->
@paneContainer.onDidStopChangingActivePaneItem(callback)
# Essential: Invoke the given callback with the current active pane item and
# with all future active pane items in the workspace.