mirror of
https://github.com/atom/atom.git
synced 2026-01-25 23:08:18 -05:00
200 lines
4.9 KiB
JavaScript
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
|