Maintain an active pane container on the workspace

This will be used by many commands that previously only interacted with
the center of the workspace.
This commit is contained in:
Nathan Sobo
2017-04-06 15:30:01 -06:00
committed by Max Brunsfeld
parent f1e30fe7cf
commit 646047f563
5 changed files with 207 additions and 22 deletions

View File

@@ -1076,6 +1076,127 @@ describe('Workspace', () => {
})
})
describe('pane containers', () => {
it('maintains the active pane and item globally across active pane containers', () => {
const leftDock = workspace.getLeftDock()
const leftItem1 = {element: document.createElement('div')}
const leftItem2 = {element: document.createElement('div')}
const leftItem3 = {element: document.createElement('div')}
const leftPane1 = leftDock.getActivePane()
leftPane1.addItems([leftItem1, leftItem2])
const leftPane2 = leftPane1.splitDown({items: [leftItem3]})
const rightDock = workspace.getRightDock()
const rightItem1 = {element: document.createElement('div')}
const rightItem2 = {element: document.createElement('div')}
const rightItem3 = {element: document.createElement('div')}
const rightPane1 = rightDock.getActivePane()
rightPane1.addItems([rightItem1, rightItem2])
const rightPane2 = rightPane1.splitDown({items: [rightItem3]})
const bottomDock = workspace.getBottomDock()
const bottomItem1 = {element: document.createElement('div')}
const bottomItem2 = {element: document.createElement('div')}
const bottomItem3 = {element: document.createElement('div')}
const bottomPane1 = bottomDock.getActivePane()
bottomPane1.addItems([bottomItem1, bottomItem2])
const bottomPane2 = bottomPane1.splitDown({items: [bottomItem3]})
const center = workspace.getCenter()
const centerItem1 = {element: document.createElement('div')}
const centerItem2 = {element: document.createElement('div')}
const centerItem3 = {element: document.createElement('div')}
const centerPane1 = center.getActivePane()
centerPane1.addItems([centerItem1, centerItem2])
const centerPane2 = centerPane1.splitDown({items: [centerItem3]})
const activePaneContainers = []
const activePanes = []
const activeItems = []
workspace.onDidChangeActivePaneContainer((container) => activePaneContainers.push(container))
workspace.onDidChangeActivePane((pane) => activePanes.push(pane))
workspace.onDidChangeActivePaneItem((item) => activeItems.push(item))
function clearEvents () {
activePaneContainers.length = 0
activePanes.length = 0
activeItems.length = 0
}
expect(workspace.getActivePaneContainer()).toBe(center)
expect(workspace.getActivePane()).toBe(centerPane2)
expect(workspace.getActivePaneItem()).toBe(centerItem3)
leftDock.activate()
expect(workspace.getActivePaneContainer()).toBe(leftDock)
expect(workspace.getActivePane()).toBe(leftPane2)
expect(workspace.getActivePaneItem()).toBe(leftItem3)
expect(activePaneContainers).toEqual([leftDock])
expect(activePanes).toEqual([leftPane2])
expect(activeItems).toEqual([leftItem3])
clearEvents()
leftPane1.activate()
leftPane1.activate()
expect(workspace.getActivePaneContainer()).toBe(leftDock)
expect(workspace.getActivePane()).toBe(leftPane1)
expect(workspace.getActivePaneItem()).toBe(leftItem1)
expect(activePaneContainers).toEqual([])
expect(activePanes).toEqual([leftPane1])
expect(activeItems).toEqual([leftItem1])
clearEvents()
leftPane1.activateItem(leftItem2)
leftPane1.activateItem(leftItem2)
expect(workspace.getActivePaneContainer()).toBe(leftDock)
expect(workspace.getActivePane()).toBe(leftPane1)
expect(workspace.getActivePaneItem()).toBe(leftItem2)
expect(activePaneContainers).toEqual([])
expect(activePanes).toEqual([])
expect(activeItems).toEqual([leftItem2])
clearEvents()
expect(rightDock.getActivePane()).toBe(rightPane2)
rightPane1.activate()
rightPane1.activate()
expect(workspace.getActivePaneContainer()).toBe(rightDock)
expect(workspace.getActivePane()).toBe(rightPane1)
expect(workspace.getActivePaneItem()).toBe(rightItem1)
expect(activePaneContainers).toEqual([rightDock])
expect(activePanes).toEqual([rightPane1])
expect(activeItems).toEqual([rightItem1])
clearEvents()
rightPane1.activateItem(rightItem2)
expect(workspace.getActivePaneContainer()).toBe(rightDock)
expect(workspace.getActivePane()).toBe(rightPane1)
expect(workspace.getActivePaneItem()).toBe(rightItem2)
expect(activePaneContainers).toEqual([])
expect(activePanes).toEqual([])
expect(activeItems).toEqual([rightItem2])
clearEvents()
expect(bottomDock.getActivePane()).toBe(bottomPane2)
bottomPane2.activate()
bottomPane2.activate()
expect(workspace.getActivePaneContainer()).toBe(bottomDock)
expect(workspace.getActivePane()).toBe(bottomPane2)
expect(workspace.getActivePaneItem()).toBe(bottomItem3)
expect(activePaneContainers).toEqual([bottomDock])
expect(activePanes).toEqual([bottomPane2])
expect(activeItems).toEqual([bottomItem3])
clearEvents()
center.activate()
center.activate()
expect(workspace.getActivePaneContainer()).toBe(center)
expect(workspace.getActivePane()).toBe(centerPane2)
expect(workspace.getActivePaneItem()).toBe(centerItem3)
expect(activePaneContainers).toEqual([center])
expect(activePanes).toEqual([centerPane2])
expect(activeItems).toEqual([centerItem3])
})
})
describe('the grammar-used hook', () => {
it('fires when opening a file or changing the grammar of an open file', () => {
let editor = null

View File

@@ -33,6 +33,7 @@ module.exports = class Dock {
this.deserializerManager = params.deserializerManager
this.notificationManager = params.notificationManager
this.viewRegistry = params.viewRegistry
this.didActivate = params.didActivate
this.didHide = params.didHide
this.paneContainer = new PaneContainer({
@@ -50,10 +51,13 @@ module.exports = class Dock {
}
this.subscriptions = new CompositeDisposable(
this.paneContainer.onDidActivatePane(() => this.open()),
this.paneContainer.observePanes(pane => {
pane.onDidRemoveItem(this.handleDidRemovePaneItem.bind(this))
})
this.paneContainer.onDidActivatePane(() => {
this.open()
this.didActivate(this)
}),
this.paneContainer.onDidDestroyPaneItem(this.handleDidRemovePaneItem.bind(this)),
this.paneContainer.onDidChangeActivePane((item) => params.didChangeActivePane(this, item)),
this.paneContainer.onDidChangeActivePaneItem((item) => params.didChangeActivePaneItem(this, item))
)
}
@@ -94,7 +98,6 @@ module.exports = class Dock {
}
activate () {
this.open()
this.getActivePane().activate()
}

View File

@@ -52,8 +52,7 @@ class PaneContainer {
deserialize (state, deserializerManager) {
if (state.version !== SERIALIZATION_VERSION) return
this.setRoot(deserializerManager.deserialize(state.root))
const activePane = find(this.getRoot().getPanes(), pane => pane.id === state.activePaneId)
this.didActivatePane(activePane != null ? activePane : this.getPanes()[0])
this.activePane = find(this.getRoot().getPanes(), pane => pane.id === state.activePaneId) || this.getPanes()[0]
if (this.config.get('core.destroyEmptyPanes')) this.destroyEmptyPanes()
}

View File

@@ -3,11 +3,18 @@
const TextEditor = require('./text-editor')
module.exports = class WorkspaceCenter {
constructor (paneContainer) {
constructor ({paneContainer, didActivate, didChangeActivePaneItem}) {
this.paneContainer = paneContainer
this.didActivate = didActivate
this.paneContainer.onDidActivatePane(() => this.didActivate(this))
this.paneContainer.onDidChangeActivePaneItem((item) => {
didChangeActivePaneItem(this, item)
})
}
activate () {}
activate () {
this.getActivePane().activate()
}
getLocation () {
return 'center'

View File

@@ -36,6 +36,9 @@ module.exports = class Workspace extends Model {
this.updateDocumentEdited = this.updateDocumentEdited.bind(this)
this.didDestroyPaneItem = this.didDestroyPaneItem.bind(this)
this.didChangeActivePaneItem = this.didChangeActivePaneItem.bind(this)
this.didChangeActivePaneOnPaneContainer = this.didChangeActivePaneOnPaneContainer.bind(this)
this.didChangeActivePaneItemOnPaneContainer = this.didChangeActivePaneItemOnPaneContainer.bind(this)
this.didActivatePaneContainer = this.didActivatePaneContainer.bind(this)
this.didHideDock = this.didHideDock.bind(this)
this.packageManager = params.packageManager
@@ -70,12 +73,17 @@ module.exports = class Workspace extends Model {
this.defaultDirectorySearcher = new DefaultDirectorySearcher()
this.consumeServices(this.packageManager)
this.center = new WorkspaceCenter(this.paneContainer)
this.center = new WorkspaceCenter({
paneContainer: this.paneContainer,
didActivate: this.didActivatePaneContainer,
didChangeActivePaneItem: this.didChangeActivePaneItemOnPaneContainer
})
this.docks = {
left: this.createDock('left'),
right: this.createDock('right'),
bottom: this.createDock('bottom')
}
this.activePaneContainer = this.center
this.panelContainers = {
top: new PanelContainer({viewRegistry: this.viewRegistry, location: 'top'}),
@@ -110,16 +118,15 @@ module.exports = class Workspace extends Model {
deserializerManager: this.deserializerManager,
notificationManager: this.notificationManager,
viewRegistry: this.viewRegistry,
didHide: this.didHideDock
didHide: this.didHideDock,
didActivate: this.didActivatePaneContainer,
didChangeActivePane: this.didChangeActivePaneOnPaneContainer,
didChangeActivePaneItem: this.didChangeActivePaneItemOnPaneContainer
})
dock.onDidDestroyPaneItem(this.didDestroyPaneItem)
return dock
}
didHideDock () {
this.getCenter().getActivePane().activate()
}
reset (packageManager) {
this.packageManager = packageManager
this.emitter.dispose()
@@ -138,12 +145,17 @@ module.exports = class Workspace extends Model {
})
this.paneContainer.onDidDestroyPaneItem(this.didDestroyPaneItem)
this.center = new WorkspaceCenter(this.paneContainer)
this.center = new WorkspaceCenter({
paneContainer: this.paneContainer,
didActivate: this.didActivatePaneContainer,
didChangeActivePaneItem: this.didChangeActivePaneItemOnPaneContainer
})
this.docks = {
left: this.createDock('left'),
right: this.createDock('right'),
bottom: this.createDock('bottom')
}
this.activePaneContainer = this.center
this.panelContainers = {
top: new PanelContainer({viewRegistry: this.viewRegistry, location: 'top'}),
@@ -212,6 +224,7 @@ module.exports = class Workspace extends Model {
this.docks[location].deserialize(serialized, deserializerManager)
}
}
this.updateWindowTitle()
}
getPackageNamesWithActiveGrammars () {
@@ -241,6 +254,32 @@ module.exports = class Workspace extends Model {
return _.uniq(packageNames)
}
didActivatePaneContainer (paneContainer) {
if (paneContainer !== this.getActivePaneContainer()) {
this.activePaneContainer = paneContainer
if (global.debug) debugger
this.emitter.emit('did-change-active-pane-container', this.activePaneContainer)
this.emitter.emit('did-change-active-pane', this.activePaneContainer.getActivePane())
this.emitter.emit('did-change-active-pane-item', this.activePaneContainer.getActivePaneItem())
}
}
didChangeActivePaneOnPaneContainer (paneContainer, pane) {
if (paneContainer === this.getActivePaneContainer()) {
this.emitter.emit('did-change-active-pane', pane)
}
}
didChangeActivePaneItemOnPaneContainer (paneContainer, item) {
if (paneContainer === this.getActivePaneContainer()) {
this.emitter.emit('did-change-active-pane-item', item)
}
}
didHideDock () {
this.getCenter().activate()
}
setHoveredDock (hoveredDock) {
this.hoveredDock = hoveredDock
_.values(this.docks).forEach(dock => {
@@ -395,6 +434,10 @@ module.exports = class Workspace extends Model {
Section: Event Subscription
*/
onDidChangeActivePaneContainer (callback) {
return this.emitter.on('did-change-active-pane-container', callback)
}
// Essential: Invoke the given callback with all current and future text
// editors in the workspace.
//
@@ -434,7 +477,7 @@ module.exports = class Workspace extends Model {
//
// Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
onDidChangeActivePaneItem (callback) {
return this.paneContainer.onDidChangeActivePaneItem(callback)
return this.emitter.on('did-change-active-pane-item', callback)
}
// Essential: Invoke the given callback when the active pane item stops
@@ -462,7 +505,10 @@ module.exports = class Workspace extends Model {
// * `item` The current active pane item.
//
// Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
observeActivePaneItem (callback) { return this.paneContainer.observeActivePaneItem(callback) }
observeActivePaneItem (callback) {
callback(this.getActivePaneItem())
return this.onDidChangeActivePaneItem(callback)
}
// Essential: Invoke the given callback whenever an item is opened. Unlike
// {::onDidAddPaneItem}, observers will be notified for items that are already
@@ -541,7 +587,9 @@ module.exports = class Workspace extends Model {
// * `pane` A {Pane} that is the current return value of {::getActivePane}.
//
// Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
onDidChangeActivePane (callback) { return this.paneContainer.onDidChangeActivePane(callback) }
onDidChangeActivePane (callback) {
return this.emitter.on('did-change-active-pane', callback)
}
// Extended: Invoke the given callback with the current active pane and when
// the active pane changes.
@@ -551,7 +599,10 @@ module.exports = class Workspace extends Model {
// * `pane` A {Pane} that is the current return value of {::getActivePane}.
//
// Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
observeActivePane (callback) { return this.paneContainer.observeActivePane(callback) }
observeActivePane (callback) {
callback(this.getActivePane())
return this.onDidChangeActivePane(callback)
}
// Extended: Invoke the given callback when a pane item is added to the
// workspace.
@@ -1065,7 +1116,7 @@ module.exports = class Workspace extends Model {
//
// Returns an pane item {Object}.
getActivePaneItem () {
return this.paneContainer.getActivePaneItem()
return this.getActivePaneContainer().getActivePaneItem()
}
// Essential: Get all text editors in the workspace.
@@ -1164,6 +1215,10 @@ module.exports = class Workspace extends Model {
Section: Panes
*/
getActivePaneContainer () {
return this.activePaneContainer
}
// Extended: Get all panes in the workspace.
//
// Returns an {Array} of {Pane}s.
@@ -1175,7 +1230,7 @@ module.exports = class Workspace extends Model {
//
// Returns a {Pane}.
getActivePane () {
return this.paneContainer.getActivePane()
return this.getActivePaneContainer().getActivePane()
}
// Extended: Make the next pane active.