mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-11-10 10:17:11 +03:00
Merge pull request #14695 from atom/jr-editors-live-in-workspace-center
Provide API for observing the active text editor
This commit is contained in:
commit
268f94b89d
@ -1,5 +1,7 @@
|
||||
/** @babel */
|
||||
|
||||
const Grim = require('grim')
|
||||
|
||||
import {it, fit, ffit, fffit, beforeEach, afterEach} from './async-spec-helpers'
|
||||
|
||||
describe('Dock', () => {
|
||||
@ -329,4 +331,13 @@ describe('Dock', () => {
|
||||
expect(() => atom.workspace.getElement().handleDragStart(dragEvent)).not.toThrow()
|
||||
})
|
||||
})
|
||||
|
||||
describe('::getActiveTextEditor()', () => {
|
||||
it('is deprecated', () => {
|
||||
spyOn(Grim, 'deprecate')
|
||||
|
||||
atom.workspace.getLeftDock().getActiveTextEditor()
|
||||
expect(Grim.deprecate.callCount).toBe(1)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -31,35 +31,35 @@ describe('Workspace', () => {
|
||||
|
||||
afterEach(() => temp.cleanupSync())
|
||||
|
||||
describe('serialization', () => {
|
||||
const simulateReload = () => {
|
||||
const workspaceState = atom.workspace.serialize()
|
||||
const projectState = atom.project.serialize({isUnloading: true})
|
||||
atom.workspace.destroy()
|
||||
atom.project.destroy()
|
||||
atom.project = new Project({
|
||||
notificationManager: atom.notifications,
|
||||
packageManager: atom.packages,
|
||||
confirm: atom.confirm.bind(atom),
|
||||
applicationDelegate: atom.applicationDelegate
|
||||
})
|
||||
atom.project.deserialize(projectState)
|
||||
atom.workspace = new Workspace({
|
||||
config: atom.config,
|
||||
project: atom.project,
|
||||
packageManager: atom.packages,
|
||||
grammarRegistry: atom.grammars,
|
||||
styleManager: atom.styles,
|
||||
deserializerManager: atom.deserializers,
|
||||
notificationManager: atom.notifications,
|
||||
applicationDelegate: atom.applicationDelegate,
|
||||
viewRegistry: atom.views,
|
||||
assert: atom.assert.bind(atom),
|
||||
textEditorRegistry: atom.textEditors
|
||||
})
|
||||
return atom.workspace.deserialize(workspaceState, atom.deserializers)
|
||||
}
|
||||
const simulateReload = () => {
|
||||
const workspaceState = workspace.serialize()
|
||||
const projectState = atom.project.serialize({isUnloading: true})
|
||||
workspace.destroy()
|
||||
atom.project.destroy()
|
||||
atom.project = new Project({
|
||||
notificationManager: atom.notifications,
|
||||
packageManager: atom.packages,
|
||||
confirm: atom.confirm.bind(atom),
|
||||
applicationDelegate: atom.applicationDelegate
|
||||
})
|
||||
atom.project.deserialize(projectState)
|
||||
workspace = atom.workspace = new Workspace({
|
||||
config: atom.config,
|
||||
project: atom.project,
|
||||
packageManager: atom.packages,
|
||||
grammarRegistry: atom.grammars,
|
||||
styleManager: atom.styles,
|
||||
deserializerManager: atom.deserializers,
|
||||
notificationManager: atom.notifications,
|
||||
applicationDelegate: atom.applicationDelegate,
|
||||
viewRegistry: atom.views,
|
||||
assert: atom.assert.bind(atom),
|
||||
textEditorRegistry: atom.textEditors
|
||||
})
|
||||
return workspace.deserialize(workspaceState, atom.deserializers)
|
||||
}
|
||||
|
||||
describe('serialization', () => {
|
||||
describe('when the workspace contains text editors', () => {
|
||||
it('constructs the view with the same panes', () => {
|
||||
const pane1 = atom.workspace.getActivePane()
|
||||
@ -120,62 +120,6 @@ describe('Workspace', () => {
|
||||
expect(atom.workspace.getTextEditors().length).toBe(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe('where a dock contains an editor', () => {
|
||||
afterEach(() => {
|
||||
atom.workspace.getRightDock().paneContainer.destroy()
|
||||
})
|
||||
|
||||
it('constructs the view with the same panes', () => {
|
||||
const pane1 = atom.workspace.getRightDock().getActivePane()
|
||||
const pane2 = pane1.splitRight({copyActiveItem: true})
|
||||
const pane3 = pane2.splitRight({copyActiveItem: true})
|
||||
let pane4 = null
|
||||
|
||||
waitsForPromise(() =>
|
||||
atom.workspace.open(null, {location: 'right'}).then(editor => editor.setText('An untitled editor.'))
|
||||
)
|
||||
|
||||
waitsForPromise(() =>
|
||||
atom.workspace.open('b', {location: 'right'}).then(editor => pane2.activateItem(editor.copy()))
|
||||
)
|
||||
|
||||
waitsForPromise(() =>
|
||||
atom.workspace.open('../sample.js', {location: 'right'}).then(editor => pane3.activateItem(editor))
|
||||
)
|
||||
|
||||
runs(() => {
|
||||
pane3.activeItem.setCursorScreenPosition([2, 4])
|
||||
pane4 = pane2.splitDown()
|
||||
})
|
||||
|
||||
waitsForPromise(() =>
|
||||
atom.workspace.open('../sample.txt', {location: 'right'}).then(editor => pane4.activateItem(editor))
|
||||
)
|
||||
|
||||
runs(() => {
|
||||
pane4.getActiveItem().setCursorScreenPosition([0, 2])
|
||||
pane2.activate()
|
||||
|
||||
simulateReload()
|
||||
|
||||
expect(atom.workspace.getTextEditors().length).toBe(5)
|
||||
const [editor1, editor2, untitledEditor, editor3, editor4] = atom.workspace.getTextEditors()
|
||||
const firstDirectory = atom.project.getDirectories()[0]
|
||||
expect(firstDirectory).toBeDefined()
|
||||
expect(editor1.getPath()).toBe(firstDirectory.resolve('b'))
|
||||
expect(editor2.getPath()).toBe(firstDirectory.resolve('../sample.txt'))
|
||||
expect(editor2.getCursorScreenPosition()).toEqual([0, 2])
|
||||
expect(editor3.getPath()).toBe(firstDirectory.resolve('b'))
|
||||
expect(editor4.getPath()).toBe(firstDirectory.resolve('../sample.js'))
|
||||
expect(editor4.getCursorScreenPosition()).toEqual([2, 4])
|
||||
expect(untitledEditor.getPath()).toBeUndefined()
|
||||
expect(untitledEditor.getText()).toBe('An untitled editor.')
|
||||
|
||||
expect(atom.workspace.getRightDock().getActiveTextEditor().getPath()).toBe(editor3.getPath())
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('::open(itemOrURI, options)', () => {
|
||||
@ -429,6 +373,13 @@ describe('Workspace', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('when attempting to open an editor in a dock', () => {
|
||||
it('opens the editor in the workspace center', async () => {
|
||||
await atom.workspace.open('sample.txt', {location: 'right'})
|
||||
expect(atom.workspace.getCenter().getActivePaneItem().getFileName()).toEqual('sample.txt')
|
||||
})
|
||||
})
|
||||
|
||||
describe('when called with an item rather than a URI', () => {
|
||||
it('adds the item itself to the workspace', async () => {
|
||||
const item = document.createElement('div')
|
||||
@ -1419,6 +1370,42 @@ describe('Workspace', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('::getActiveTextEditor()', () => {
|
||||
describe("when the workspace center's active pane item is a text editor", () => {
|
||||
describe('when the workspace center has focus', function () {
|
||||
it('returns the text editor', () => {
|
||||
const workspaceCenter = workspace.getCenter()
|
||||
const editor = new TextEditor()
|
||||
workspaceCenter.getActivePane().activateItem(editor)
|
||||
workspaceCenter.activate()
|
||||
|
||||
expect(workspace.getActiveTextEditor()).toBe(editor)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when a dock has focus', function () {
|
||||
it('returns the text editor', () => {
|
||||
const workspaceCenter = workspace.getCenter()
|
||||
const editor = new TextEditor()
|
||||
workspaceCenter.getActivePane().activateItem(editor)
|
||||
workspace.getLeftDock().activate()
|
||||
|
||||
expect(workspace.getActiveTextEditor()).toBe(editor)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("when the workspace center's active pane item is not a text editor", () => {
|
||||
it('returns undefined', () => {
|
||||
const workspaceCenter = workspace.getCenter()
|
||||
const nonEditorItem = document.createElement('div')
|
||||
workspaceCenter.getActivePane().activateItem(nonEditorItem)
|
||||
|
||||
expect(workspace.getActiveTextEditor()).toBeUndefined()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('::observeTextEditors()', () => {
|
||||
it('invokes the observer with current and future text editors', () => {
|
||||
const observed = []
|
||||
@ -1435,6 +1422,92 @@ describe('Workspace', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('::observeActiveTextEditor()', () => {
|
||||
it('invokes the observer with current active text editor and each time a different text editor becomes active', () => {
|
||||
const pane = workspace.getCenter().getActivePane()
|
||||
observed = []
|
||||
|
||||
const inactiveEditorBeforeRegisteringObserver = new TextEditor()
|
||||
const activeEditorBeforeRegisteringObserver = new TextEditor()
|
||||
pane.activateItem(inactiveEditorBeforeRegisteringObserver)
|
||||
pane.activateItem(activeEditorBeforeRegisteringObserver)
|
||||
|
||||
workspace.observeActiveTextEditor(editor => observed.push(editor))
|
||||
|
||||
const editorAddedAfterRegisteringObserver = new TextEditor()
|
||||
const nonEditorItemAddedAfterRegisteringObserver = document.createElement('div')
|
||||
pane.activateItem(editorAddedAfterRegisteringObserver)
|
||||
|
||||
expect(observed).toEqual(
|
||||
[activeEditorBeforeRegisteringObserver, editorAddedAfterRegisteringObserver]
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('::onDidChangeActiveTextEditor()', () => {
|
||||
let center, pane, observed
|
||||
|
||||
beforeEach(() => {
|
||||
center = workspace.getCenter()
|
||||
pane = center.getActivePane()
|
||||
observed = []
|
||||
})
|
||||
|
||||
it("invokes the observer when a text editor becomes the workspace center's active pane item while a dock has focus", () => {
|
||||
workspace.onDidChangeActiveTextEditor(editor => observed.push(editor))
|
||||
|
||||
const dock = workspace.getLeftDock()
|
||||
dock.activate()
|
||||
expect(atom.workspace.getActivePaneContainer()).toBe(dock)
|
||||
|
||||
const editor = new TextEditor()
|
||||
center.getActivePane().activateItem(editor)
|
||||
expect(atom.workspace.getActivePaneContainer()).toBe(dock)
|
||||
|
||||
expect(observed).toEqual([editor])
|
||||
})
|
||||
|
||||
it('invokes the observer when the last text editor is closed', () => {
|
||||
const editor = new TextEditor()
|
||||
pane.activateItem(editor)
|
||||
|
||||
workspace.onDidChangeActiveTextEditor(editor => observed.push(editor))
|
||||
pane.destroyItem(editor)
|
||||
expect(observed).toEqual([undefined])
|
||||
})
|
||||
|
||||
it("invokes the observer when the workspace center's active pane item changes from an editor item to a non-editor item", () => {
|
||||
const editor = new TextEditor()
|
||||
const nonEditorItem = document.createElement('div')
|
||||
pane.activateItem(editor)
|
||||
|
||||
workspace.onDidChangeActiveTextEditor(editor => observed.push(editor))
|
||||
pane.activateItem(nonEditorItem)
|
||||
expect(observed).toEqual([undefined])
|
||||
})
|
||||
|
||||
it("does not invoke the observer when the workspace center's active pane item changes from a non-editor item to another non-editor item", () => {
|
||||
workspace.onDidChangeActiveTextEditor(editor => observed.push(editor))
|
||||
|
||||
const nonEditorItem1 = document.createElement('div')
|
||||
const nonEditorItem2 = document.createElement('div')
|
||||
pane.activateItem(nonEditorItem1)
|
||||
pane.activateItem(nonEditorItem1)
|
||||
|
||||
expect(observed).toEqual([])
|
||||
})
|
||||
|
||||
it('invokes the observer when closing the one and only text editor after deserialization', async () => {
|
||||
pane.activateItem(new TextEditor())
|
||||
|
||||
simulateReload()
|
||||
|
||||
workspace.onDidChangeActiveTextEditor(editor => observed.push(editor))
|
||||
workspace.closeActivePaneItemOrEmptyPaneOrWindow()
|
||||
expect(observed).toEqual([undefined])
|
||||
})
|
||||
})
|
||||
|
||||
describe('when an editor is destroyed', () => {
|
||||
it('removes the editor', () => {
|
||||
let editor = null
|
||||
|
29
src/dock.js
29
src/dock.js
@ -4,6 +4,7 @@ const _ = require('underscore-plus')
|
||||
const {CompositeDisposable} = require('event-kit')
|
||||
const PaneContainer = require('./pane-container')
|
||||
const TextEditor = require('./text-editor')
|
||||
const Grim = require('grim')
|
||||
|
||||
const MINIMUM_SIZE = 100
|
||||
const DEFAULT_INITIAL_SIZE = 300
|
||||
@ -384,21 +385,6 @@ module.exports = class Dock {
|
||||
Section: Event Subscription
|
||||
*/
|
||||
|
||||
// Essential: Invoke the given callback with all current and future text
|
||||
// editors in the dock.
|
||||
//
|
||||
// * `callback` {Function} to be called with current and future text editors.
|
||||
// * `editor` An {TextEditor} that is present in {::getTextEditors} at the time
|
||||
// of subscription or that is added at some later time.
|
||||
//
|
||||
// Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
|
||||
observeTextEditors (callback) {
|
||||
for (const textEditor of this.getTextEditors()) {
|
||||
callback(textEditor)
|
||||
}
|
||||
return this.onDidAddTextEditor(({textEditor}) => callback(textEditor))
|
||||
}
|
||||
|
||||
// Essential: Invoke the given callback with all current and future panes items
|
||||
// in the dock.
|
||||
//
|
||||
@ -583,18 +569,13 @@ module.exports = class Dock {
|
||||
return this.paneContainer.getActivePaneItem()
|
||||
}
|
||||
|
||||
// Essential: Get all text editors in the dock.
|
||||
// Deprecated: Get the active item if it is a {TextEditor}.
|
||||
//
|
||||
// Returns an {Array} of {TextEditor}s.
|
||||
getTextEditors () {
|
||||
return this.paneContainer.getTextEditors()
|
||||
}
|
||||
|
||||
// Essential: Get the active item if it is an {TextEditor}.
|
||||
//
|
||||
// Returns an {TextEditor} or `undefined` if the current active item is not an
|
||||
// Returns a {TextEditor} or `undefined` if the current active item is not a
|
||||
// {TextEditor}.
|
||||
getActiveTextEditor () {
|
||||
Grim.deprecate('Text editors are not allowed in docks. Use atom.workspace.getActiveTextEditor() instead.')
|
||||
|
||||
const activeItem = this.getActivePaneItem()
|
||||
if (activeItem instanceof TextEditor) { return activeItem }
|
||||
}
|
||||
|
@ -3628,6 +3628,9 @@ class TextEditor extends Model
|
||||
})
|
||||
@component.element
|
||||
|
||||
getAllowedLocations: ->
|
||||
['center']
|
||||
|
||||
# Essential: Retrieves the greyed out placeholder of a mini editor.
|
||||
#
|
||||
# Returns a {String}.
|
||||
|
@ -216,6 +216,7 @@ module.exports = class Workspace extends Model {
|
||||
bottom: this.createDock('bottom')
|
||||
}
|
||||
this.activePaneContainer = this.paneContainers.center
|
||||
this.hasActiveTextEditor = false
|
||||
|
||||
this.panelContainers = {
|
||||
top: new PanelContainer({viewRegistry: this.viewRegistry, location: 'top'}),
|
||||
@ -296,6 +297,7 @@ module.exports = class Workspace extends Model {
|
||||
bottom: this.createDock('bottom')
|
||||
}
|
||||
this.activePaneContainer = this.paneContainers.center
|
||||
this.hasActiveTextEditor = false
|
||||
|
||||
this.panelContainers = {
|
||||
top: new PanelContainer({viewRegistry: this.viewRegistry, location: 'top'}),
|
||||
@ -371,6 +373,8 @@ module.exports = class Workspace extends Model {
|
||||
this.paneContainers.center.deserialize(state.paneContainer, deserializerManager)
|
||||
}
|
||||
|
||||
this.hasActiveTextEditor = this.getActiveTextEditor() != null
|
||||
|
||||
this.updateWindowTitle()
|
||||
}
|
||||
|
||||
@ -422,6 +426,16 @@ module.exports = class Workspace extends Model {
|
||||
this.didChangeActivePaneItem(item)
|
||||
this.emitter.emit('did-change-active-pane-item', item)
|
||||
}
|
||||
|
||||
if (paneContainer === this.getCenter()) {
|
||||
const hadActiveTextEditor = this.hasActiveTextEditor
|
||||
this.hasActiveTextEditor = item instanceof TextEditor
|
||||
|
||||
if (this.hasActiveTextEditor || hadActiveTextEditor) {
|
||||
const itemValue = this.hasActiveTextEditor ? item : undefined
|
||||
this.emitter.emit('did-change-active-text-editor', itemValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
didChangeActivePaneItem (item) {
|
||||
@ -648,6 +662,18 @@ module.exports = class Workspace extends Model {
|
||||
return this.emitter.on('did-stop-changing-active-pane-item', callback)
|
||||
}
|
||||
|
||||
// Essential: Invoke the given callback when a text editor becomes the active
|
||||
// text editor and when there is no longer an active text editor.
|
||||
//
|
||||
// * `callback` {Function} to be called when the active text editor changes.
|
||||
// * `editor` The active {TextEditor} or undefined if there is no longer an
|
||||
// active text editor.
|
||||
//
|
||||
// Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
|
||||
onDidChangeActiveTextEditor (callback) {
|
||||
return this.emitter.on('did-change-active-text-editor', callback)
|
||||
}
|
||||
|
||||
// Essential: Invoke the given callback with the current active pane item and
|
||||
// with all future active pane items in the workspace.
|
||||
//
|
||||
@ -660,6 +686,21 @@ module.exports = class Workspace extends Model {
|
||||
return this.onDidChangeActivePaneItem(callback)
|
||||
}
|
||||
|
||||
// Essential: Invoke the given callback with the current active text editor
|
||||
// (if any), with all future active text editors, and when there is no longer
|
||||
// an active text editor.
|
||||
//
|
||||
// * `callback` {Function} to be called when the active text editor changes.
|
||||
// * `editor` The active {TextEditor} or undefined if there is not an
|
||||
// active text editor.
|
||||
//
|
||||
// Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
|
||||
observeActiveTextEditor (callback) {
|
||||
callback(this.getActiveTextEditor())
|
||||
|
||||
return this.onDidChangeActiveTextEditor(callback)
|
||||
}
|
||||
|
||||
// Essential: Invoke the given callback whenever an item is opened. Unlike
|
||||
// {::onDidAddPaneItem}, observers will be notified for items that are already
|
||||
// present in the workspace when they are reopened.
|
||||
@ -1282,12 +1323,12 @@ module.exports = class Workspace extends Model {
|
||||
return this.getPaneItems().filter(item => item instanceof TextEditor)
|
||||
}
|
||||
|
||||
// Essential: Get the active item if it is an {TextEditor}.
|
||||
// Essential: Get the workspace center's active item if it is a {TextEditor}.
|
||||
//
|
||||
// Returns an {TextEditor} or `undefined` if the current active item is not an
|
||||
// {TextEditor}.
|
||||
// Returns a {TextEditor} or `undefined` if the workspace center's current
|
||||
// active item is not a {TextEditor}.
|
||||
getActiveTextEditor () {
|
||||
const activeItem = this.getActivePaneItem()
|
||||
const activeItem = this.getCenter().getActivePaneItem()
|
||||
if (activeItem instanceof TextEditor) { return activeItem }
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user