Files
atom/src/pane-axis.js
2018-08-28 10:24:31 -07:00

200 lines
4.9 KiB
JavaScript

const {Emitter, CompositeDisposable} = require('event-kit')
const {flatten} = require('underscore-plus')
const Model = require('./model')
const PaneAxisElement = require('./pane-axis-element')
class PaneAxis extends Model {
static deserialize (state, {deserializers, views}) {
state.children = state.children.map(childState => deserializers.deserialize(childState))
return new PaneAxis(state, views)
}
constructor ({orientation, children, flexScale}, viewRegistry) {
super()
this.parent = null
this.container = null
this.orientation = orientation
this.viewRegistry = viewRegistry
this.emitter = new Emitter()
this.subscriptionsByChild = new WeakMap()
this.subscriptions = new CompositeDisposable()
this.flexScale = flexScale != null ? flexScale : 1
this.children = []
if (children) {
for (let child of children) {
this.addChild(child)
}
}
}
serialize () {
return {
deserializer: 'PaneAxis',
children: this.children.map(child => child.serialize()),
orientation: this.orientation,
flexScale: this.flexScale
}
}
getElement () {
if (!this.element) {
this.element = new PaneAxisElement().initialize(this, this.viewRegistry)
}
return this.element
}
getFlexScale () {
return this.flexScale
}
setFlexScale (flexScale) {
this.flexScale = flexScale
this.emitter.emit('did-change-flex-scale', this.flexScale)
return this.flexScale
}
getParent () {
return this.parent
}
setParent (parent) {
this.parent = parent
return this.parent
}
getContainer () {
return this.container
}
setContainer (container) {
if (container && (container !== this.container)) {
this.container = container
this.children.forEach(child => child.setContainer(container))
}
}
getOrientation () {
return this.orientation
}
getChildren () {
return this.children.slice()
}
getPanes () {
return flatten(this.children.map(child => child.getPanes()))
}
getItems () {
return flatten(this.children.map(child => child.getItems()))
}
onDidAddChild (fn) {
return this.emitter.on('did-add-child', fn)
}
onDidRemoveChild (fn) {
return this.emitter.on('did-remove-child', fn)
}
onDidReplaceChild (fn) {
return this.emitter.on('did-replace-child', fn)
}
onDidDestroy (fn) {
return this.emitter.once('did-destroy', fn)
}
onDidChangeFlexScale (fn) {
return this.emitter.on('did-change-flex-scale', fn)
}
observeFlexScale (fn) {
fn(this.flexScale)
return this.onDidChangeFlexScale(fn)
}
addChild (child, index = this.children.length) {
this.children.splice(index, 0, child)
child.setParent(this)
child.setContainer(this.container)
this.subscribeToChild(child)
return this.emitter.emit('did-add-child', {child, index})
}
adjustFlexScale () {
// get current total flex scale of children
let total = 0
for (var child of this.children) { total += child.getFlexScale() }
const needTotal = this.children.length
// set every child's flex scale by the ratio
for (child of this.children) {
child.setFlexScale((needTotal * child.getFlexScale()) / total)
}
}
removeChild (child, replacing = false) {
const index = this.children.indexOf(child)
if (index === -1) { throw new Error('Removing non-existent child') }
this.unsubscribeFromChild(child)
this.children.splice(index, 1)
this.adjustFlexScale()
this.emitter.emit('did-remove-child', {child, index})
if (!replacing && this.children.length < 2) {
this.reparentLastChild()
}
}
replaceChild (oldChild, newChild) {
this.unsubscribeFromChild(oldChild)
this.subscribeToChild(newChild)
newChild.setParent(this)
newChild.setContainer(this.container)
const index = this.children.indexOf(oldChild)
this.children.splice(index, 1, newChild)
this.emitter.emit('did-replace-child', {oldChild, newChild, index})
}
insertChildBefore (currentChild, newChild) {
const index = this.children.indexOf(currentChild)
return this.addChild(newChild, index)
}
insertChildAfter (currentChild, newChild) {
const index = this.children.indexOf(currentChild)
return this.addChild(newChild, index + 1)
}
reparentLastChild () {
const lastChild = this.children[0]
lastChild.setFlexScale(this.flexScale)
this.parent.replaceChild(this, lastChild)
this.destroy()
}
subscribeToChild (child) {
const subscription = child.onDidDestroy(() => this.removeChild(child))
this.subscriptionsByChild.set(child, subscription)
this.subscriptions.add(subscription)
}
unsubscribeFromChild (child) {
const subscription = this.subscriptionsByChild.get(child)
this.subscriptions.remove(subscription)
subscription.dispose()
}
destroyed () {
this.subscriptions.dispose()
this.emitter.emit('did-destroy')
this.emitter.dispose()
}
}
module.exports = PaneAxis