mirror of
https://github.com/atom/atom.git
synced 2026-01-23 22:08:08 -05:00
Add onDidStopChangingActivePaneItem for async callbacks
`onDidChangeActivePaneItem` is called synchronously when the active pane item changes, and several non-critical actions preform work on that event. Critical UI feedback, like changing the active tab, needs to happen synchronously, but most other functionality should be run asynchronously.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user