Skip to content

Commit

Permalink
[webview] fix computation of view columns
Browse files Browse the repository at this point in the history
Before rows were ignored, now Theia sorts all tab bars by left and top positions and then assigns:
- (1, 2, 3, 3, 3, ...) positions for tab bars in first row
- (4, 5, 6, 6, 6, ...) positions for tab bars in second row
- (7, 8, 9, 9, 9,....) positions for tab bars in third row
- (7, 8, 9, 9, 9,....) positions for tab bars in following rows

Signed-off-by: Anton Kosyakov <anton.kosyakov@typefox.io>
  • Loading branch information
akosyakov committed Nov 22, 2019
1 parent 5d7eb1d commit fc49b2c
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 25 deletions.
2 changes: 1 addition & 1 deletion packages/plugin-ext/src/common/plugin-api-rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1254,7 +1254,7 @@ export interface WebviewsExt {
viewType: string,
title: string,
state: any,
position: number,
viewState: WebviewPanelViewState,
options: theia.WebviewOptions & theia.WebviewPanelOptions): PromiseLike<void>;
}

Expand Down
68 changes: 51 additions & 17 deletions packages/plugin-ext/src/main/browser/view-column-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { injectable, inject } from 'inversify';
import { Emitter, Event } from '@theia/core/lib/common/event';
import { ApplicationShell } from '@theia/core/lib/browser/shell/application-shell';
import { toArray } from '@phosphor/algorithm';
import { TabBar, Widget } from '@phosphor/widgets';

@injectable()
export class ViewColumnService {
Expand Down Expand Up @@ -51,26 +52,59 @@ export class ViewColumnService {
}

updateViewColumns(): void {
const positionIds = new Map<number, string[]>();
toArray(this.shell.mainPanel.tabBars()).forEach(tabBar => {
if (!tabBar.node.style.left) {
return;
}
const position = parseInt(tabBar.node.style.left);
const viewColumnIds = tabBar.titles.map(title => title.owner.id);
positionIds.set(position, viewColumnIds);
});
this.columnValues.clear();
this.viewColumnIds.clear();
[...positionIds.keys()].sort((a, b) => a - b).forEach((key: number, viewColumn: number) => {
positionIds.get(key)!.forEach((id: string) => {
this.columnValues.set(id, viewColumn);
if (!this.viewColumnIds.has(viewColumn)) {
this.viewColumnIds.set(viewColumn, []);

const rows = new Map<number, Set<number>>();
const columns = new Map<number, Map<number, TabBar<Widget>>>();
for (const tabBar of toArray(this.shell.mainPanel.tabBars())) {
if (!tabBar.node.style.top || !tabBar.node.style.left) {
continue;
}
const top = parseInt(tabBar.node.style.top);
const left = parseInt(tabBar.node.style.left);

const row = rows.get(top) || new Set<number>();
row.add(left);
rows.set(top, row);

const column = columns.get(left) || new Map<number, TabBar<Widget>>();
column.set(top, tabBar);
columns.set(left, column);
}
const firstRow = rows.get([...rows.keys()].sort()[0]);
if (!firstRow) {
return;
}
const lefts = [...firstRow.keys()].sort();
for (let i = 0; i < lefts.length; i++) {
const column = columns.get(lefts[i]);
if (!column) {
break;
}
const cellIndexes = [...column.keys()].sort();
let viewColumn = Math.min(i, 2);
for (let j = 0; j < cellIndexes.length; j++) {
const cell = column.get(cellIndexes[j]);
if (!cell) {
break;
}
this.viewColumnIds.get(viewColumn)!.push(id);
});
});
this.setViewColumn(cell, viewColumn);
if (viewColumn < 7) {
viewColumn += 3;
}
}
}
}

protected setViewColumn(tabBar: TabBar<Widget>, viewColumn: number): void {
const ids = [];
for (const title of tabBar.titles) {
const id = title.owner.id;
ids.push(id);
this.columnValues.set(id, viewColumn);
}
this.viewColumnIds.set(viewColumn, ids);
}

getViewColumnIds(viewColumn: number): string[] {
Expand Down
8 changes: 4 additions & 4 deletions packages/plugin-ext/src/main/browser/webviews-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export class WebviewsMainImpl implements WebviewsMain, Disposable {

protected hookWebview(view: WebviewWidget): void {
const handle = view.identifier.id;
this.toDispose.push(view.onDidChangeVisibility(() => this.updateViewState(view)));
this.toDispose.push(view.onMessage(data => this.proxy.$onMessage(handle, data)));
view.disposed.connect(() => {
if (this.toDispose.disposed) {
Expand Down Expand Up @@ -206,9 +207,8 @@ export class WebviewsMainImpl implements WebviewsMain, Disposable {

const options = widget.options;
const { allowScripts, localResourceRoots, ...contentOptions } = widget.contentOptions;
this.viewColumnService.updateViewColumns();
const position = this.viewColumnService.getViewColumn(widget.id) || 0;
await this.proxy.$deserializeWebviewPanel(handle, widget.viewType, title, state, position, {
this.updateViewState(widget);
await this.proxy.$deserializeWebviewPanel(handle, widget.viewType, title, state, widget.viewState, {
enableScripts: allowScripts,
localResourceRoots: localResourceRoots && localResourceRoots.map(root => URI.parse(root)),
...contentOptions,
Expand All @@ -224,7 +224,7 @@ export class WebviewsMainImpl implements WebviewsMain, Disposable {
}
}, 100);

private async updateViewState(widget: WebviewWidget, viewColumn?: number | undefined): Promise<void> {
private updateViewState(widget: WebviewWidget, viewColumn?: number | undefined): void {
const viewState: Mutable<WebviewPanelViewState> = {
active: this.shell.activeWidget === widget,
visible: !widget.isHidden,
Expand Down
7 changes: 4 additions & 3 deletions packages/plugin-ext/src/plugin/webviews.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export class WebviewsExtImpl implements WebviewsExt {
title: string,
// tslint:disable-next-line:no-any
state: any,
position: number,
viewState: WebviewPanelViewState,
options: theia.WebviewOptions & theia.WebviewPanelOptions): PromiseLike<void> {
if (!this.initData) {
return Promise.reject(new Error('Webviews are not initialized'));
Expand All @@ -90,7 +90,9 @@ export class WebviewsExtImpl implements WebviewsExt {
const { serializer, plugin } = entry;

const webview = new WebviewImpl(viewId, this.proxy, options, this.initData, this.workspace, plugin);
const revivedPanel = new WebviewPanelImpl(viewId, this.proxy, viewType, title, toViewColumn(position)!, options, webview);
const revivedPanel = new WebviewPanelImpl(viewId, this.proxy, viewType, title, toViewColumn(viewState.position)!, options, webview);
revivedPanel.setActive(viewState.active);
revivedPanel.setVisible(viewState.visible);
this.webviewPanels.set(viewId, revivedPanel);
return serializer.deserializeWebviewPanel(revivedPanel, state);
}
Expand Down Expand Up @@ -254,7 +256,6 @@ export class WebviewPanelImpl implements theia.WebviewPanel {
private readonly _webview: WebviewImpl
) {
this._showOptions = typeof showOptions === 'object' ? showOptions : { viewColumn: showOptions as theia.ViewColumn };
this.setViewColumn(undefined);
}

dispose(): void {
Expand Down

0 comments on commit fc49b2c

Please sign in to comment.