Files
atom/src/pane-element.js
2019-05-31 18:33:56 +02:00

219 lines
5.7 KiB
JavaScript

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, here: true });
}
};
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
});