Merge pull request #13954 from atom/fb-mdt-panel-container-to-js

Convert Panel Container to JavaScript
This commit is contained in:
Nathan Sobo
2017-03-07 19:48:48 -07:00
committed by GitHub
8 changed files with 463 additions and 366 deletions

View File

@@ -1,137 +0,0 @@
Panel = require '../src/panel'
PanelContainer = require '../src/panel-container'
describe "PanelContainerElement", ->
[jasmineContent, element, container] = []
class TestPanelContainerItem
constructior: ->
class TestPanelContainerItemElement extends HTMLElement
createdCallback: ->
@classList.add('test-root')
initialize: (@model) ->
this
TestPanelContainerItemElement = document.registerElement 'atom-test-container-item-element', prototype: TestPanelContainerItemElement.prototype
beforeEach ->
jasmineContent = document.body.querySelector('#jasmine-content')
atom.views.addViewProvider TestPanelContainerItem, (model) ->
new TestPanelContainerItemElement().initialize(model)
container = new PanelContainer({location: 'left'})
element = atom.views.getView(container)
jasmineContent.appendChild(element)
it 'has a location class with value from the model', ->
expect(element).toHaveClass 'left'
it 'removes the element when the container is destroyed', ->
expect(element.parentNode).toBe jasmineContent
container.destroy()
expect(element.parentNode).not.toBe jasmineContent
describe "adding and removing panels", ->
it "allows panels to be inserted at any position", ->
panel1 = new Panel({item: new TestPanelContainerItem(), priority: 10})
panel2 = new Panel({item: new TestPanelContainerItem(), priority: 5})
panel3 = new Panel({item: new TestPanelContainerItem(), priority: 8})
container.addPanel(panel1)
container.addPanel(panel2)
container.addPanel(panel3)
expect(element.childNodes[2].getModel()).toBe(panel1)
expect(element.childNodes[1].getModel()).toBe(panel3)
expect(element.childNodes[0].getModel()).toBe(panel2)
describe "when the container is at the left location", ->
it "adds atom-panel elements when a new panel is added to the container; removes them when the panels are destroyed", ->
expect(element.childNodes.length).toBe 0
panel1 = new Panel({item: new TestPanelContainerItem()})
container.addPanel(panel1)
expect(element.childNodes.length).toBe 1
expect(element.childNodes[0]).toHaveClass 'left'
expect(element.childNodes[0]).toHaveClass 'tool-panel' # legacy selector support
expect(element.childNodes[0]).toHaveClass 'panel-left' # legacy selector support
expect(element.childNodes[0].tagName).toBe 'ATOM-PANEL'
panel2 = new Panel({item: new TestPanelContainerItem()})
container.addPanel(panel2)
expect(element.childNodes.length).toBe 2
expect(atom.views.getView(panel1).style.display).not.toBe 'none'
expect(atom.views.getView(panel2).style.display).not.toBe 'none'
panel1.destroy()
expect(element.childNodes.length).toBe 1
panel2.destroy()
expect(element.childNodes.length).toBe 0
describe "when the container is at the bottom location", ->
beforeEach ->
container = new PanelContainer({location: 'bottom'})
element = atom.views.getView(container)
jasmineContent.appendChild(element)
it "adds atom-panel elements when a new panel is added to the container; removes them when the panels are destroyed", ->
expect(element.childNodes.length).toBe 0
panel1 = new Panel({item: new TestPanelContainerItem(), className: 'one'})
container.addPanel(panel1)
expect(element.childNodes.length).toBe 1
expect(element.childNodes[0]).toHaveClass 'bottom'
expect(element.childNodes[0]).toHaveClass 'tool-panel' # legacy selector support
expect(element.childNodes[0]).toHaveClass 'panel-bottom' # legacy selector support
expect(element.childNodes[0].tagName).toBe 'ATOM-PANEL'
expect(atom.views.getView(panel1)).toHaveClass 'one'
panel2 = new Panel({item: new TestPanelContainerItem(), className: 'two'})
container.addPanel(panel2)
expect(element.childNodes.length).toBe 2
expect(atom.views.getView(panel2)).toHaveClass 'two'
panel1.destroy()
expect(element.childNodes.length).toBe 1
panel2.destroy()
expect(element.childNodes.length).toBe 0
describe "when the container is modal", ->
beforeEach ->
container = new PanelContainer({location: 'modal'})
element = atom.views.getView(container)
jasmineContent.appendChild(element)
it "allows only one panel to be visible at a time", ->
panel1 = new Panel({item: new TestPanelContainerItem()})
container.addPanel(panel1)
expect(atom.views.getView(panel1).style.display).not.toBe 'none'
panel2 = new Panel({item: new TestPanelContainerItem()})
container.addPanel(panel2)
expect(atom.views.getView(panel1).style.display).toBe 'none'
expect(atom.views.getView(panel2).style.display).not.toBe 'none'
panel1.show()
expect(atom.views.getView(panel1).style.display).not.toBe 'none'
expect(atom.views.getView(panel2).style.display).toBe 'none'
it "adds the 'modal' class to panels", ->
panel1 = new Panel({item: new TestPanelContainerItem()})
container.addPanel(panel1)
expect(atom.views.getView(panel1)).toHaveClass 'modal'
# legacy selector support
expect(atom.views.getView(panel1)).not.toHaveClass 'tool-panel'
expect(atom.views.getView(panel1)).toHaveClass 'overlay'
expect(atom.views.getView(panel1)).toHaveClass 'from-top'

View File

@@ -0,0 +1,165 @@
'use strict'
/* global HTMLElement */
const Panel = require('../src/panel')
const PanelContainer = require('../src/panel-container')
describe('PanelContainerElement', () => {
let jasmineContent, element, container
class TestPanelContainerItem {
}
class TestPanelContainerItemElement_ extends HTMLElement {
createdCallback () {
this.classList.add('test-root')
}
initialize (model) {
this.model = model
return this
}
}
const TestPanelContainerItemElement = document.registerElement(
'atom-test-container-item-element',
{prototype: TestPanelContainerItemElement_.prototype}
)
beforeEach(() => {
jasmineContent = document.body.querySelector('#jasmine-content')
atom.views.addViewProvider(
TestPanelContainerItem,
model => new TestPanelContainerItemElement().initialize(model)
)
container = new PanelContainer({location: 'left'})
element = atom.views.getView(container)
jasmineContent.appendChild(element)
})
it('has a location class with value from the model', () => {
expect(element).toHaveClass('left')
})
it('removes the element when the container is destroyed', () => {
expect(element.parentNode).toBe(jasmineContent)
container.destroy()
expect(element.parentNode).not.toBe(jasmineContent)
})
describe('adding and removing panels', () => {
it('allows panels to be inserted at any position', () => {
const panel1 = new Panel({item: new TestPanelContainerItem(), priority: 10})
const panel2 = new Panel({item: new TestPanelContainerItem(), priority: 5})
const panel3 = new Panel({item: new TestPanelContainerItem(), priority: 8})
container.addPanel(panel1)
container.addPanel(panel2)
container.addPanel(panel3)
expect(element.childNodes[2].getModel()).toBe(panel1)
expect(element.childNodes[1].getModel()).toBe(panel3)
expect(element.childNodes[0].getModel()).toBe(panel2)
})
describe('when the container is at the left location', () =>
it('adds atom-panel elements when a new panel is added to the container; removes them when the panels are destroyed', () => {
expect(element.childNodes.length).toBe(0)
const panel1 = new Panel({item: new TestPanelContainerItem()})
container.addPanel(panel1)
expect(element.childNodes.length).toBe(1)
expect(element.childNodes[0]).toHaveClass('left')
expect(element.childNodes[0]).toHaveClass('tool-panel') // legacy selector support
expect(element.childNodes[0]).toHaveClass('panel-left') // legacy selector support
expect(element.childNodes[0].tagName).toBe('ATOM-PANEL')
const panel2 = new Panel({item: new TestPanelContainerItem()})
container.addPanel(panel2)
expect(element.childNodes.length).toBe(2)
expect(atom.views.getView(panel1).style.display).not.toBe('none')
expect(atom.views.getView(panel2).style.display).not.toBe('none')
panel1.destroy()
expect(element.childNodes.length).toBe(1)
panel2.destroy()
expect(element.childNodes.length).toBe(0)
})
)
describe('when the container is at the bottom location', () => {
beforeEach(() => {
container = new PanelContainer({location: 'bottom'})
element = atom.views.getView(container)
jasmineContent.appendChild(element)
})
it('adds atom-panel elements when a new panel is added to the container; removes them when the panels are destroyed', () => {
expect(element.childNodes.length).toBe(0)
const panel1 = new Panel({item: new TestPanelContainerItem(), className: 'one'})
container.addPanel(panel1)
expect(element.childNodes.length).toBe(1)
expect(element.childNodes[0]).toHaveClass('bottom')
expect(element.childNodes[0]).toHaveClass('tool-panel') // legacy selector support
expect(element.childNodes[0]).toHaveClass('panel-bottom') // legacy selector support
expect(element.childNodes[0].tagName).toBe('ATOM-PANEL')
expect(atom.views.getView(panel1)).toHaveClass('one')
const panel2 = new Panel({item: new TestPanelContainerItem(), className: 'two'})
container.addPanel(panel2)
expect(element.childNodes.length).toBe(2)
expect(atom.views.getView(panel2)).toHaveClass('two')
panel1.destroy()
expect(element.childNodes.length).toBe(1)
panel2.destroy()
expect(element.childNodes.length).toBe(0)
})
})
})
describe('when the container is modal', () => {
beforeEach(() => {
container = new PanelContainer({location: 'modal'})
element = atom.views.getView(container)
jasmineContent.appendChild(element)
})
it('allows only one panel to be visible at a time', () => {
const panel1 = new Panel({item: new TestPanelContainerItem()})
container.addPanel(panel1)
expect(atom.views.getView(panel1).style.display).not.toBe('none')
const panel2 = new Panel({item: new TestPanelContainerItem()})
container.addPanel(panel2)
expect(atom.views.getView(panel1).style.display).toBe('none')
expect(atom.views.getView(panel2).style.display).not.toBe('none')
panel1.show()
expect(atom.views.getView(panel1).style.display).not.toBe('none')
expect(atom.views.getView(panel2).style.display).toBe('none')
})
it("adds the 'modal' class to panels", () => {
const panel1 = new Panel({item: new TestPanelContainerItem()})
container.addPanel(panel1)
expect(atom.views.getView(panel1)).toHaveClass('modal')
// legacy selector support
expect(atom.views.getView(panel1)).not.toHaveClass('tool-panel')
expect(atom.views.getView(panel1)).toHaveClass('overlay')
expect(atom.views.getView(panel1)).toHaveClass('from-top')
})
})
})

View File

@@ -1,113 +0,0 @@
Panel = require '../src/panel'
PanelContainer = require '../src/panel-container'
describe "PanelContainer", ->
[container] = []
class TestPanelItem
constructor: ->
beforeEach ->
container = new PanelContainer
describe "::addPanel(panel)", ->
it 'emits an onDidAddPanel event with the index the panel was inserted at', ->
container.onDidAddPanel addPanelSpy = jasmine.createSpy()
panel1 = new Panel(item: new TestPanelItem())
container.addPanel(panel1)
expect(addPanelSpy).toHaveBeenCalledWith({panel: panel1, index: 0})
panel2 = new Panel(item: new TestPanelItem())
container.addPanel(panel2)
expect(addPanelSpy).toHaveBeenCalledWith({panel: panel2, index: 1})
describe "when a panel is destroyed", ->
it 'emits an onDidRemovePanel event with the index of the removed item', ->
container.onDidRemovePanel removePanelSpy = jasmine.createSpy()
panel1 = new Panel(item: new TestPanelItem())
container.addPanel(panel1)
panel2 = new Panel(item: new TestPanelItem())
container.addPanel(panel2)
expect(removePanelSpy).not.toHaveBeenCalled()
panel2.destroy()
expect(removePanelSpy).toHaveBeenCalledWith({panel: panel2, index: 1})
panel1.destroy()
expect(removePanelSpy).toHaveBeenCalledWith({panel: panel1, index: 0})
describe "::destroy()", ->
it "destroys the container and all of its panels", ->
destroyedPanels = []
panel1 = new Panel(item: new TestPanelItem())
panel1.onDidDestroy -> destroyedPanels.push(panel1)
container.addPanel(panel1)
panel2 = new Panel(item: new TestPanelItem())
panel2.onDidDestroy -> destroyedPanels.push(panel2)
container.addPanel(panel2)
container.destroy()
expect(container.getPanels().length).toBe(0)
expect(destroyedPanels).toEqual([panel1, panel2])
describe "panel priority", ->
describe 'left / top panel container', ->
[initialPanel] = []
beforeEach ->
# 'left' logic is the same as 'top'
container = new PanelContainer({location: 'left'})
initialPanel = new Panel(item: new TestPanelItem())
container.addPanel(initialPanel)
describe 'when a panel with low priority is added', ->
it 'is inserted at the beginning of the list', ->
container.onDidAddPanel addPanelSpy = jasmine.createSpy()
panel = new Panel(item: new TestPanelItem(), priority: 0)
container.addPanel(panel)
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 0})
expect(container.getPanels()[0]).toBe panel
describe 'when a panel with priority between two other panels is added', ->
it 'is inserted at the between the two panels', ->
panel = new Panel(item: new TestPanelItem(), priority: 1000)
container.addPanel(panel)
container.onDidAddPanel addPanelSpy = jasmine.createSpy()
panel = new Panel(item: new TestPanelItem(), priority: 101)
container.addPanel(panel)
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 1})
expect(container.getPanels()[1]).toBe panel
describe 'right / bottom panel container', ->
[initialPanel] = []
beforeEach ->
# 'bottom' logic is the same as 'right'
container = new PanelContainer({location: 'right'})
initialPanel = new Panel(item: new TestPanelItem())
container.addPanel(initialPanel)
describe 'when a panel with high priority is added', ->
it 'is inserted at the beginning of the list', ->
container.onDidAddPanel addPanelSpy = jasmine.createSpy()
panel = new Panel(item: new TestPanelItem(), priority: 1000)
container.addPanel(panel)
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 0})
expect(container.getPanels()[0]).toBe panel
describe 'when a panel with low priority is added', ->
it 'is inserted at the end of the list', ->
container.onDidAddPanel addPanelSpy = jasmine.createSpy()
panel = new Panel(item: new TestPanelItem(), priority: 0)
container.addPanel(panel)
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 1})
expect(container.getPanels()[1]).toBe panel

View File

@@ -0,0 +1,142 @@
'use strict'
const Panel = require('../src/panel')
const PanelContainer = require('../src/panel-container')
describe('PanelContainer', () => {
let container
class TestPanelItem {
}
beforeEach(() => {
container = new PanelContainer()
})
describe('::addPanel(panel)', () => {
it('emits an onDidAddPanel event with the index the panel was inserted at', () => {
const addPanelSpy = jasmine.createSpy()
container.onDidAddPanel(addPanelSpy)
const panel1 = new Panel({item: new TestPanelItem()})
container.addPanel(panel1)
expect(addPanelSpy).toHaveBeenCalledWith({panel: panel1, index: 0})
const panel2 = new Panel({item: new TestPanelItem()})
container.addPanel(panel2)
expect(addPanelSpy).toHaveBeenCalledWith({panel: panel2, index: 1})
})
})
describe('when a panel is destroyed', () => {
it('emits an onDidRemovePanel event with the index of the removed item', () => {
const removePanelSpy = jasmine.createSpy()
container.onDidRemovePanel(removePanelSpy)
const panel1 = new Panel({item: new TestPanelItem()})
container.addPanel(panel1)
const panel2 = new Panel({item: new TestPanelItem()})
container.addPanel(panel2)
expect(removePanelSpy).not.toHaveBeenCalled()
panel2.destroy()
expect(removePanelSpy).toHaveBeenCalledWith({panel: panel2, index: 1})
panel1.destroy()
expect(removePanelSpy).toHaveBeenCalledWith({panel: panel1, index: 0})
})
})
describe('::destroy()', () => {
it('destroys the container and all of its panels', () => {
const destroyedPanels = []
const panel1 = new Panel({item: new TestPanelItem()})
panel1.onDidDestroy(() => { destroyedPanels.push(panel1) })
container.addPanel(panel1)
const panel2 = new Panel({item: new TestPanelItem()})
panel2.onDidDestroy(() => { destroyedPanels.push(panel2) })
container.addPanel(panel2)
container.destroy()
expect(container.getPanels().length).toBe(0)
expect(destroyedPanels).toEqual([panel1, panel2])
})
})
describe('panel priority', () => {
describe('left / top panel container', () => {
let initialPanel
beforeEach(() => {
// 'left' logic is the same as 'top'
container = new PanelContainer({location: 'left'})
initialPanel = new Panel({item: new TestPanelItem()})
container.addPanel(initialPanel)
})
describe('when a panel with low priority is added', () => {
it('is inserted at the beginning of the list', () => {
const addPanelSpy = jasmine.createSpy()
container.onDidAddPanel(addPanelSpy)
const panel = new Panel({item: new TestPanelItem(), priority: 0})
container.addPanel(panel)
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 0})
expect(container.getPanels()[0]).toBe(panel)
})
})
describe('when a panel with priority between two other panels is added', () => {
it('is inserted at the between the two panels', () => {
const addPanelSpy = jasmine.createSpy()
let panel = new Panel({item: new TestPanelItem(), priority: 1000})
container.addPanel(panel)
container.onDidAddPanel(addPanelSpy)
panel = new Panel({item: new TestPanelItem(), priority: 101})
container.addPanel(panel)
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 1})
expect(container.getPanels()[1]).toBe(panel)
})
})
})
describe('right / bottom panel container', () => {
let initialPanel
beforeEach(() => {
// 'bottom' logic is the same as 'right'
container = new PanelContainer({location: 'right'})
initialPanel = new Panel({item: new TestPanelItem()})
container.addPanel(initialPanel)
})
describe('when a panel with high priority is added', () => {
it('is inserted at the beginning of the list', () => {
const addPanelSpy = jasmine.createSpy()
container.onDidAddPanel(addPanelSpy)
const panel = new Panel({item: new TestPanelItem(), priority: 1000})
container.addPanel(panel)
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 0})
expect(container.getPanels()[0]).toBe(panel)
})
})
describe('when a panel with low priority is added', () => {
it('is inserted at the end of the list', () => {
const addPanelSpy = jasmine.createSpy()
container.onDidAddPanel(addPanelSpy)
const panel = new Panel({item: new TestPanelItem(), priority: 0})
container.addPanel(panel)
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 1})
expect(container.getPanels()[1]).toBe(panel)
})
})
})
})
})

View File

@@ -1,45 +0,0 @@
{CompositeDisposable} = require 'event-kit'
class PanelContainerElement extends HTMLElement
createdCallback: ->
@subscriptions = new CompositeDisposable
initialize: (@model, {@views}) ->
throw new Error("Must pass a views parameter when initializing PanelContainerElements") unless @views?
@subscriptions.add @model.onDidAddPanel(@panelAdded.bind(this))
@subscriptions.add @model.onDidDestroy(@destroyed.bind(this))
@classList.add(@model.getLocation())
this
getModel: -> @model
panelAdded: ({panel, index}) ->
panelElement = @views.getView(panel)
panelElement.classList.add(@model.getLocation())
if @model.isModal()
panelElement.classList.add("overlay", "from-top")
else
panelElement.classList.add("tool-panel", "panel-#{@model.getLocation()}")
if index >= @childNodes.length
@appendChild(panelElement)
else
referenceItem = @childNodes[index]
@insertBefore(panelElement, referenceItem)
if @model.isModal()
@hideAllPanelsExcept(panel)
@subscriptions.add panel.onDidChangeVisible (visible) =>
@hideAllPanelsExcept(panel) if visible
destroyed: ->
@subscriptions.dispose()
@parentNode?.removeChild(this)
hideAllPanelsExcept: (excludedPanel) ->
for panel in @model.getPanels()
panel.hide() unless panel is excludedPanel
return
module.exports = PanelContainerElement = document.registerElement 'atom-panel-container', prototype: PanelContainerElement.prototype

View File

@@ -0,0 +1,65 @@
'use strict'
/* global HTMLElement */
const {CompositeDisposable} = require('event-kit')
class PanelContainerElement extends HTMLElement {
createdCallback () {
this.subscriptions = new CompositeDisposable()
}
initialize (model, {views}) {
this.model = model
this.views = views
if (this.views == null) {
throw new Error('Must pass a views parameter when initializing PanelContainerElements')
}
this.subscriptions.add(this.model.onDidAddPanel(this.panelAdded.bind(this)))
this.subscriptions.add(this.model.onDidDestroy(this.destroyed.bind(this)))
this.classList.add(this.model.getLocation())
return this
}
getModel () { return this.model }
panelAdded ({panel, index}) {
const panelElement = this.views.getView(panel)
panelElement.classList.add(this.model.getLocation())
if (this.model.isModal()) {
panelElement.classList.add('overlay', 'from-top')
} else {
panelElement.classList.add('tool-panel', `panel-${this.model.getLocation()}`)
}
if (index >= this.childNodes.length) {
this.appendChild(panelElement)
} else {
const referenceItem = this.childNodes[index]
this.insertBefore(panelElement, referenceItem)
}
if (this.model.isModal()) {
this.hideAllPanelsExcept(panel)
this.subscriptions.add(panel.onDidChangeVisible(visible => {
if (visible) { this.hideAllPanelsExcept(panel) }
}))
}
}
destroyed () {
this.subscriptions.dispose()
if (this.parentNode != null) {
this.parentNode.removeChild(this)
}
}
hideAllPanelsExcept (excludedPanel) {
for (let panel of this.model.getPanels()) {
if (panel !== excludedPanel) { panel.hide() }
}
}
}
module.exports = document.registerElement('atom-panel-container', {prototype: PanelContainerElement.prototype})

View File

@@ -1,71 +0,0 @@
{Emitter, CompositeDisposable} = require 'event-kit'
module.exports =
class PanelContainer
constructor: ({@location}={}) ->
@emitter = new Emitter
@subscriptions = new CompositeDisposable
@panels = []
destroy: ->
panel.destroy() for panel in @getPanels()
@subscriptions.dispose()
@emitter.emit 'did-destroy', this
@emitter.dispose()
###
Section: Event Subscription
###
onDidAddPanel: (callback) ->
@emitter.on 'did-add-panel', callback
onDidRemovePanel: (callback) ->
@emitter.on 'did-remove-panel', callback
onDidDestroy: (callback) ->
@emitter.on 'did-destroy', callback
###
Section: Panels
###
getLocation: -> @location
isModal: -> @location is 'modal'
getPanels: -> @panels.slice()
addPanel: (panel) ->
@subscriptions.add panel.onDidDestroy(@panelDestroyed.bind(this))
index = @getPanelIndex(panel)
if index is @panels.length
@panels.push(panel)
else
@panels.splice(index, 0, panel)
@emitter.emit 'did-add-panel', {panel, index}
panel
panelForItem: (item) ->
for panel in @panels
return panel if panel.getItem() is item
null
panelDestroyed: (panel) ->
index = @panels.indexOf(panel)
if index > -1
@panels.splice(index, 1)
@emitter.emit 'did-remove-panel', {panel, index}
getPanelIndex: (panel) ->
priority = panel.getPriority()
if @location in ['bottom', 'right']
for p, i in @panels by -1
return i + 1 if priority < p.getPriority()
0
else
for p, i in @panels
return i if priority < p.getPriority()
@panels.length

91
src/panel-container.js Normal file
View File

@@ -0,0 +1,91 @@
'use strict'
const {Emitter, CompositeDisposable} = require('event-kit')
module.exports = class PanelContainer {
constructor ({location} = {}) {
this.location = location
this.emitter = new Emitter()
this.subscriptions = new CompositeDisposable()
this.panels = []
}
destroy () {
for (let panel of this.getPanels()) { panel.destroy() }
this.subscriptions.dispose()
this.emitter.emit('did-destroy', this)
this.emitter.dispose()
}
/*
Section: Event Subscription
*/
onDidAddPanel (callback) {
return this.emitter.on('did-add-panel', callback)
}
onDidRemovePanel (callback) {
return this.emitter.on('did-remove-panel', callback)
}
onDidDestroy (callback) {
return this.emitter.on('did-destroy', callback)
}
/*
Section: Panels
*/
getLocation () { return this.location }
isModal () { return this.location === 'modal' }
getPanels () { return this.panels.slice() }
addPanel (panel) {
this.subscriptions.add(panel.onDidDestroy(this.panelDestroyed.bind(this)))
const index = this.getPanelIndex(panel)
if (index === this.panels.length) {
this.panels.push(panel)
} else {
this.panels.splice(index, 0, panel)
}
this.emitter.emit('did-add-panel', {panel, index})
return panel
}
panelForItem (item) {
for (let panel of this.panels) {
if (panel.getItem() === item) { return panel }
}
return null
}
panelDestroyed (panel) {
const index = this.panels.indexOf(panel)
if (index > -1) {
this.panels.splice(index, 1)
this.emitter.emit('did-remove-panel', {panel, index})
}
}
getPanelIndex (panel) {
const priority = panel.getPriority()
if (['bottom', 'right'].includes(this.location)) {
for (let i = this.panels.length - 1; i >= 0; i--) {
const p = this.panels[i]
if (priority < p.getPriority()) { return i + 1 }
}
return 0
} else {
for (let i = 0; i < this.panels.length; i++) {
const p = this.panels[i]
if (priority < p.getPriority()) { return i }
}
return this.panels.length
}
}
}