Skip to content

Commit

Permalink
[core] propagate phosphor events to view container part's widget
Browse files Browse the repository at this point in the history
Signed-off-by: Anton Kosyakov <anton.kosyakov@typefox.io>
  • Loading branch information
akosyakov committed Jul 31, 2019
1 parent d294062 commit f37cb19
Showing 1 changed file with 89 additions and 62 deletions.
151 changes: 89 additions & 62 deletions packages/core/src/browser/view-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { v4 } from 'uuid';
import { IIterator, toArray, find, some, every, map } from '@phosphor/algorithm';
import {
Widget, EXPANSION_TOGGLE_CLASS, COLLAPSED_CLASS, MessageLoop, Message, SplitPanel, BaseWidget,
addEventListener, SplitLayout, LayoutItem
addEventListener, SplitLayout, LayoutItem, PanelLayout
} from './widgets';
import { Event, Emitter } from '../common/event';
import { Deferred } from '../common/promise-util';
Expand Down Expand Up @@ -47,19 +47,23 @@ export class ViewContainer extends BaseWidget implements StatefulWidget, Applica
super();
this.id = `view-container-widget-${v4()}`;
this.addClass('theia-view-container');
const layout = new ViewContainerLayout({
renderer: SplitPanel.defaultRenderer,
orientation: this.orientation,
spacing: 2,
headerSize: ViewContainerPart.HEADER_HEIGHT,
animationDuration: 200
}, services.splitPositionHandler);
this.panel = new SplitPanel({ layout });
const layout = new PanelLayout();
this.layout = layout;
this.panel = new SplitPanel({
layout: new ViewContainerLayout({
renderer: SplitPanel.defaultRenderer,
orientation: this.orientation,
spacing: 2,
headerSize: ViewContainerPart.HEADER_HEIGHT,
animationDuration: 200
}, services.splitPositionHandler)
});
layout.addWidget(this.panel);
for (const { widget, options } of inputs) {
this.addWidget(widget, options);
}
this.attached.promise.then(() => {
this.layout.setPartSizes(inputs.map(({ options }) => options ? options.weight : undefined));
this.containerLayout.setPartSizes(inputs.map(({ options }) => options ? options.weight : undefined));
});

const { commandRegistry, menuRegistry, contextMenuRenderer } = this.services;
Expand All @@ -75,7 +79,7 @@ export class ViewContainer extends BaseWidget implements StatefulWidget, Applica
if (toHide) {
return toHide.canHide && !toHide.isHidden;
} else {
return some(this.layout.iter(), part => !part.isHidden);
return some(this.containerLayout.iter(), part => !part.isHidden);
}
}
});
Expand All @@ -85,7 +89,7 @@ export class ViewContainer extends BaseWidget implements StatefulWidget, Applica
});
this.toDispose.pushAll([
addEventListener(this.node, 'contextmenu', event => {
if (event.button === 2 && every(this.layout.iter(), part => !!part.isHidden)) {
if (event.button === 2 && every(this.containerLayout.iter(), part => !!part.isHidden)) {
event.stopPropagation();
event.preventDefault();
contextMenuRenderer.render({ menuPath: this.contextMenuPath, anchor: event });
Expand All @@ -101,35 +105,35 @@ export class ViewContainer extends BaseWidget implements StatefulWidget, Applica
if (element instanceof Element) {
const closestPart = ViewContainerPart.closestPart(element);
if (closestPart && closestPart.id) {
return find(this.layout.iter(), part => part.id === closestPart.id);
return find(this.containerLayout.iter(), part => part.id === closestPart.id);
}
}
return undefined;
}

addWidget(widget: Widget, options?: ViewContainer.Factory.WidgetOptions): Disposable {
if (find(this.layout.iter(), ({ wrapped }) => wrapped.id === widget.id)) {
if (find(this.containerLayout.iter(), ({ wrapped }) => wrapped.id === widget.id)) {
return Disposable.NULL;
}
const description = this.services.widgetManager.getDescription(widget);
const partId = description ? JSON.stringify(description) : widget.id;
const newPart = new ViewContainerPart(widget, partId, this.id, options);
this.registerPart(newPart);
if (options && options.order !== undefined) {
const index = this.layout.widgets.findIndex(part => part.options.order === undefined || part.options.order > options.order!);
const index = this.containerLayout.widgets.findIndex(part => part.options.order === undefined || part.options.order > options.order!);
if (index >= 0) {
this.layout.insertWidget(index, newPart);
this.containerLayout.insertWidget(index, newPart);
} else {
this.layout.addWidget(newPart);
this.containerLayout.addWidget(newPart);
}
} else {
this.layout.addWidget(newPart);
this.containerLayout.addWidget(newPart);
}
this.refreshMenu(newPart);
this.update();
return new DisposableCollection(
Disposable.create(() => this.removeWidget(widget)),
newPart.onCollapsed(() => this.layout.updateCollapsed(newPart, this.enableAnimation)),
newPart.onCollapsed(() => this.containerLayout.updateCollapsed(newPart, this.enableAnimation)),
newPart.onMoveBefore(toMoveId => this.moveBefore(toMoveId, newPart.id)),
newPart.onContextMenu(event => {
if (event.button === 2) {
Expand All @@ -143,21 +147,21 @@ export class ViewContainer extends BaseWidget implements StatefulWidget, Applica
}

removeWidget(widget: Widget): boolean {
const part = find(this.layout.iter(), ({ wrapped }) => wrapped.id === widget.id);
const part = find(this.containerLayout.iter(), ({ wrapped }) => wrapped.id === widget.id);
if (!part) {
return false;
}
this.unregisterPart(part);
this.layout.removeWidget(part);
this.containerLayout.removeWidget(part);
this.update();
return true;
}

getTrackableWidgets(): ViewContainerPart[] {
return this.layout.widgets;
return this.containerLayout.widgets;
}

get layout(): ViewContainerLayout {
get containerLayout(): ViewContainerLayout {
return this.panel.layout as ViewContainerLayout;
}

Expand All @@ -175,11 +179,11 @@ export class ViewContainer extends BaseWidget implements StatefulWidget, Applica
if (!this.isVisible && this.lastVisibleState) {
return this.lastVisibleState;
}
const parts = this.layout.widgets;
const availableSize = this.layout.getAvailableSize();
const parts = this.containerLayout.widgets;
const availableSize = this.containerLayout.getAvailableSize();
const orientation = this.orientation;
const partStates = parts.map(part => {
let size = this.layout.getPartSize(part);
let size = this.containerLayout.getPartSize(part);
if (size && size > ViewContainerPart.HEADER_HEIGHT && orientation === 'vertical') {
size -= ViewContainerPart.HEADER_HEIGHT;
}
Expand All @@ -200,19 +204,19 @@ export class ViewContainer extends BaseWidget implements StatefulWidget, Applica
*/
restoreState(state: ViewContainer.State): void {
if (state.parts) {
const partStates = state.parts.filter(partState => some(this.layout.iter(), p => p.partId === partState.partId));
const partStates = state.parts.filter(partState => some(this.containerLayout.iter(), p => p.partId === partState.partId));

// Reorder the parts according to the stored state
for (let index = 0; index < partStates.length; index++) {
const partState = partStates[index];
const currentIndex = this.layout.widgets.findIndex(p => p.partId === partState.partId);
const currentIndex = this.containerLayout.widgets.findIndex(p => p.partId === partState.partId);
if (currentIndex > index) {
this.layout.moveWidget(currentIndex, index);
this.containerLayout.moveWidget(currentIndex, index);
}
}

// Restore visibility and collapsed state
const parts = this.layout.widgets;
const parts = this.containerLayout.widgets;
for (let index = 0; index < parts.length; index++) {
const part = parts[index];
const partState = partStates.find(s => part.partId === s.partId);
Expand All @@ -229,7 +233,7 @@ export class ViewContainer extends BaseWidget implements StatefulWidget, Applica

// Restore part sizes
this.attached.promise.then(() => {
this.layout.setPartSizes(partStates.map(partState => partState.relativeSize));
this.containerLayout.setPartSizes(partStates.map(partState => partState.relativeSize));
});
}
}
Expand All @@ -243,13 +247,13 @@ export class ViewContainer extends BaseWidget implements StatefulWidget, Applica
const commandId = this.toggleVisibilityCommandId(toRegister);
commandRegistry.registerCommand({ id: commandId }, {
execute: () => {
const toHide = find(this.layout.iter(), part => part.id === toRegister.id);
const toHide = find(this.containerLayout.iter(), part => part.id === toRegister.id);
if (toHide) {
this.toggleVisibility(toHide);
}
},
isToggled: () => {
const widgetToToggle = find(this.layout.iter(), part => part.id === toRegister.id);
const widgetToToggle = find(this.containerLayout.iter(), part => part.id === toRegister.id);
if (widgetToToggle) {
return !widgetToToggle.isHidden;
}
Expand All @@ -271,7 +275,7 @@ export class ViewContainer extends BaseWidget implements StatefulWidget, Applica
menuRegistry.registerMenuAction([...this.contextMenuPath, '1_widgets'], {
commandId: commandId,
label: part.wrapped.title.label,
order: this.layout.widgets.indexOf(part).toString()
order: this.containerLayout.widgets.indexOf(part).toString()
});
}
}
Expand Down Expand Up @@ -305,47 +309,30 @@ export class ViewContainer extends BaseWidget implements StatefulWidget, Applica
}

protected moveBefore(toMovedId: string, moveBeforeThisId: string): void {
const parts = this.layout.widgets;
const parts = this.containerLayout.widgets;
const toMoveIndex = parts.findIndex(part => part.id === toMovedId);
const moveBeforeThisIndex = parts.findIndex(part => part.id === moveBeforeThisId);
if (toMoveIndex >= 0 && moveBeforeThisIndex >= 0) {
this.layout.moveWidget(toMoveIndex, moveBeforeThisIndex);
this.containerLayout.moveWidget(toMoveIndex, moveBeforeThisIndex);
for (let index = Math.min(toMoveIndex, moveBeforeThisIndex); index < parts.length; index++) {
this.refreshMenu(parts[index]);
}
}
}

protected onResize(msg: Widget.ResizeMessage): void {
for (const widget of [this.panel, ...this.layout.widgets]) {
MessageLoop.sendMessage(widget, Widget.ResizeMessage.UnknownSize);
}
super.onResize(msg);
}

protected onUpdateRequest(msg: Message): void {
for (const widget of [this.panel, ...this.layout.widgets]) {
widget.update();
}
super.onUpdateRequest(msg);
}

protected onActivateRequest(msg: Message): void {
super.onActivateRequest(msg);
this.panel.activate();
}

protected onAfterAttach(msg: Message): void {
const orientation = this.orientation;
this.layout.orientation = orientation;
this.containerLayout.orientation = orientation;
if (orientation === 'horizontal') {
for (const part of this.layout.widgets) {
for (const part of this.containerLayout.widgets) {
part.collapsed = false;
}
}
if (!this.panel.isAttached) {
Widget.attach(this.panel, this.node);
}
super.onAfterAttach(msg);
requestAnimationFrame(() => this.attached.resolve());
}
Expand Down Expand Up @@ -479,7 +466,7 @@ export class ViewContainerPart extends BaseWidget {
return;
}
this._collapsed = collapsed;
this.body.style.display = collapsed ? 'none' : 'block';
this.wrapped.setHidden(collapsed);
const toggleIcon = this.header.querySelector(`span.${EXPANSION_TOGGLE_CLASS}`);
if (toggleIcon) {
if (collapsed) {
Expand Down Expand Up @@ -638,25 +625,65 @@ export class ViewContainerPart extends BaseWidget {
};
}

protected onResize(msg: Widget.ResizeMessage): void {
if (this.wrapped.isAttached && !this.collapsed) {
MessageLoop.sendMessage(this.wrapped, Widget.ResizeMessage.UnknownSize);
}
super.onResize(msg);
}

protected onUpdateRequest(msg: Message): void {
if (this.wrapped.isAttached && !this.collapsed) {
MessageLoop.sendMessage(this.wrapped, msg);
}
super.onUpdateRequest(msg);
}

protected onAfterAttach(msg: Message): void {
if (!this.wrapped.isAttached) {
Widget.attach(this.wrapped, this.body);
MessageLoop.sendMessage(this.wrapped, Widget.Msg.BeforeAttach);
// tslint:disable-next-line:no-null-keyword
this.body.insertBefore(this.wrapped.node, null);
MessageLoop.sendMessage(this.wrapped, Widget.Msg.AfterAttach);
}
super.onAfterAttach(msg);
}

protected onBeforeDetach(msg: Message): void {
super.onBeforeDetach(msg);
if (this.wrapped.isAttached) {
Widget.detach(this.wrapped);
MessageLoop.sendMessage(this.wrapped, Widget.Msg.BeforeDetach);
this.wrapped.node.parentNode!.removeChild(this.wrapped.node);
MessageLoop.sendMessage(this.wrapped, Widget.Msg.AfterDetach);
}
}

protected onUpdateRequest(msg: Message): void {
if (this.wrapped.isAttached) {
this.wrapped.update();
protected onBeforeShow(msg: Message): void {
if (this.wrapped.isAttached && !this.collapsed) {
MessageLoop.sendMessage(this.wrapped, msg);
}
super.onBeforeShow(msg);
}

protected onAfterShow(msg: Message): void {
super.onAfterShow(msg);
if (this.wrapped.isAttached && !this.collapsed) {
MessageLoop.sendMessage(this.wrapped, msg);
}
}

protected onBeforeHide(msg: Message): void {
if (this.wrapped.isAttached && this.collapsed) {
MessageLoop.sendMessage(this.wrapped, msg);
}
super.onBeforeShow(msg);
}

protected onAfterHide(msg: Message): void {
super.onAfterHide(msg);
if (this.wrapped.isAttached && this.collapsed) {
MessageLoop.sendMessage(this.wrapped, msg);
}
super.onUpdateRequest(msg);
}

}
Expand Down

0 comments on commit f37cb19

Please sign in to comment.