const path = require('path') const {CompositeDisposable} = require('event-kit') class PaneElement extends HTMLElement { createdCallback () { this.attached = false this.subscriptions = new CompositeDisposable() this.inlineDisplayStyles = new WeakMap() this.initializeContent() this.subscribeToDOMEvents() } attachedCallback () { this.attached = true if (this.model.isFocused()) { this.focus() } } detachedCallback () { this.attached = false } initializeContent () { this.setAttribute('class', 'pane') this.setAttribute('tabindex', -1) this.itemViews = document.createElement('div') this.appendChild(this.itemViews) this.itemViews.setAttribute('class', 'item-views') } subscribeToDOMEvents () { const handleFocus = event => { if ( !( this.isActivating || this.model.isDestroyed() || this.contains(event.relatedTarget) ) ) { this.model.focus() } if (event.target !== this) return const view = this.getActiveView() if (view) { view.focus() event.stopPropagation() } } const handleBlur = event => { if (!this.contains(event.relatedTarget)) { this.model.blur() } } const handleDragOver = event => { event.preventDefault() event.stopPropagation() } const handleDrop = event => { event.preventDefault() event.stopPropagation() this.getModel().activate() const pathsToOpen = [...event.dataTransfer.files].map(file => file.path) if (pathsToOpen.length > 0) { this.applicationDelegate.open({pathsToOpen}) } } this.addEventListener('focus', handleFocus, true) this.addEventListener('blur', handleBlur, true) this.addEventListener('dragover', handleDragOver) this.addEventListener('drop', handleDrop) } initialize (model, {views, applicationDelegate}) { this.model = model this.views = views this.applicationDelegate = applicationDelegate if (this.views == null) { throw new Error( 'Must pass a views parameter when initializing PaneElements' ) } if (this.applicationDelegate == null) { throw new Error( 'Must pass an applicationDelegate parameter when initializing PaneElements' ) } this.subscriptions.add(this.model.onDidActivate(this.activated.bind(this))) this.subscriptions.add( this.model.observeActive(this.activeStatusChanged.bind(this)) ) this.subscriptions.add( this.model.observeActiveItem(this.activeItemChanged.bind(this)) ) this.subscriptions.add( this.model.onDidRemoveItem(this.itemRemoved.bind(this)) ) this.subscriptions.add( this.model.onDidDestroy(this.paneDestroyed.bind(this)) ) this.subscriptions.add( this.model.observeFlexScale(this.flexScaleChanged.bind(this)) ) return this } getModel () { return this.model } activated () { this.isActivating = true if (!this.hasFocus()) { // Don't steal focus from children. this.focus() } this.isActivating = false } activeStatusChanged (active) { if (active) { this.classList.add('active') } else { this.classList.remove('active') } } activeItemChanged (item) { delete this.dataset.activeItemName delete this.dataset.activeItemPath if (this.changePathDisposable != null) { this.changePathDisposable.dispose() } if (item == null) { return } const hasFocus = this.hasFocus() const itemView = this.views.getView(item) const itemPath = typeof item.getPath === 'function' ? item.getPath() : null if (itemPath) { this.dataset.activeItemName = path.basename(itemPath) this.dataset.activeItemPath = itemPath if (item.onDidChangePath != null) { this.changePathDisposable = item.onDidChangePath(() => { const itemPath = item.getPath() this.dataset.activeItemName = path.basename(itemPath) this.dataset.activeItemPath = itemPath }) } } if (!this.itemViews.contains(itemView)) { this.itemViews.appendChild(itemView) } for (const child of this.itemViews.children) { if (child === itemView) { if (this.attached) { this.showItemView(child) } } else { this.hideItemView(child) } } if (hasFocus) { itemView.focus() } } showItemView (itemView) { const inlineDisplayStyle = this.inlineDisplayStyles.get(itemView) if (inlineDisplayStyle != null) { itemView.style.display = inlineDisplayStyle } else { itemView.style.display = '' } } hideItemView (itemView) { const inlineDisplayStyle = itemView.style.display if (inlineDisplayStyle !== 'none') { if (inlineDisplayStyle != null) { this.inlineDisplayStyles.set(itemView, inlineDisplayStyle) } itemView.style.display = 'none' } } itemRemoved ({item, index, destroyed}) { const viewToRemove = this.views.getView(item) if (viewToRemove) { viewToRemove.remove() } } paneDestroyed () { this.subscriptions.dispose() if (this.changePathDisposable != null) { this.changePathDisposable.dispose() } } flexScaleChanged (flexScale) { this.style.flexGrow = flexScale } getActiveView () { return this.views.getView(this.model.getActiveItem()) } hasFocus () { return ( this === document.activeElement || this.contains(document.activeElement) ) } } module.exports = document.registerElement('atom-pane', { prototype: PaneElement.prototype })