Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[vscode] support when closure for views #5855

Merged
merged 1 commit into from
Aug 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions packages/core/src/browser/context-key-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
********************************************************************************/

import { injectable } from 'inversify';
import { Emitter } from '../common/event';

export interface ContextKey<T> {
set(value: T | undefined): void;
Expand All @@ -30,8 +31,19 @@ export namespace ContextKey {
});
}

export interface ContextKeyChangeEvent {
affects(keys: Set<string>): boolean;
}

@injectable()
export class ContextKeyService {

protected readonly onDidChangeEmitter = new Emitter<ContextKeyChangeEvent>();
readonly onDidChange = this.onDidChangeEmitter.event;
protected fireDidChange(event: ContextKeyChangeEvent): void {
this.onDidChangeEmitter.fire(event);
}

createKey<T>(key: string, defaultValue: T | undefined): ContextKey<T> {
return ContextKey.None;
}
Expand Down
22 changes: 11 additions & 11 deletions packages/core/src/browser/view-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ export class ViewContainer extends BaseWidget implements StatefulWidget, Applica
execute: () => {
const toHide = find(this.containerLayout.iter(), part => part.id === toRegister.id);
if (toHide) {
this.toggleVisibility(toHide);
toHide.setHidden(!toHide.isHidden);
}
},
isToggled: () => {
Expand Down Expand Up @@ -469,15 +469,6 @@ export class ViewContainer extends BaseWidget implements StatefulWidget, Applica
return `${this.id}:toggle-visibility`;
}

protected toggleVisibility(part: ViewContainerPart): void {
if (part.canHide) {
part.setHidden(!part.isHidden);
if (!part.isHidden) {
part.collapsed = false;
}
}
}

protected moveBefore(toMovedId: string, moveBeforeThisId: string): void {
const parts = this.getParts();
const toMoveIndex = parts.findIndex(part => part.id === toMovedId);
Expand Down Expand Up @@ -519,7 +510,6 @@ export class ViewContainer extends BaseWidget implements StatefulWidget, Applica
return undefined;
}
part.setHidden(false);
part.collapsed = false;
return part;
}

Expand Down Expand Up @@ -697,6 +687,16 @@ export class ViewContainerPart extends BaseWidget {
this.collapsedEmitter.fire(collapsed);
}

setHidden(hidden: boolean): void {
if (!this.canHide) {
return;
}
super.setHidden(hidden);
if (!this.isHidden) {
this.collapsed = false;
}
}

get canHide(): boolean {
return this.options.canHide === undefined || this.options.canHide;
}
Expand Down
11 changes: 10 additions & 1 deletion packages/monaco/src/browser/monaco-context-key-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

import { injectable, inject } from 'inversify';
import { injectable, inject, postConstruct } from 'inversify';
import { ContextKeyService, ContextKey } from '@theia/core/lib/browser/context-key-service';

@injectable()
Expand All @@ -23,6 +23,15 @@ export class MonacoContextKeyService extends ContextKeyService {
@inject(monaco.contextKeyService.ContextKeyService)
protected readonly contextKeyService: monaco.contextKeyService.ContextKeyService;

@postConstruct()
protected init(): void {
this.contextKeyService.onDidChangeContext(e =>
this.fireDidChange({
affects: keys => e.affectsSome(keys)
})
);
}

createKey<T>(key: string, defaultValue: T | undefined): ContextKey<T> {
return this.contextKeyService.createKey(key, defaultValue);
}
Expand Down
5 changes: 5 additions & 0 deletions packages/monaco/src/typings/monaco/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1102,12 +1102,17 @@ declare module monaco.contextKeyService {

export interface IContext { }

export interface IContextKeyChangeEvent {
affectsSome(keys: Set<string>): boolean;
}

export class ContextKeyService implements IContextKeyService {
constructor(configurationService: monaco.services.IConfigurationService);
createScoped(target?: HTMLElement): IContextKeyService;
getContext(target?: HTMLElement): IContext;
createKey<T>(key: string, defaultValue: T | undefined): IContextKey<T>;
contextMatchesRules(rules: monaco.contextkey.ContextKeyExpr | undefined): boolean;
onDidChangeContext: monaco.IEvent<IContextKeyChangeEvent>;
}

}
Expand Down
2 changes: 2 additions & 0 deletions packages/plugin-ext/src/common/plugin-protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export interface PluginPackageViewContainer {
export interface PluginPackageView {
id: string;
name: string;
when?: string;
}

export interface PluginPackageCommand {
Expand Down Expand Up @@ -497,6 +498,7 @@ export interface ViewContainer {
export interface View {
id: string;
name: string;
when?: string;
}

export interface PluginCommand {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,8 @@ export class TheiaPluginScanner implements PluginScanner {
private readView(rawView: PluginPackageView): View {
const result: View = {
id: rawView.id,
name: rawView.name
name: rawView.name,
when: rawView.when
};

return result;
Expand Down
68 changes: 65 additions & 3 deletions packages/plugin-ext/src/main/browser/view/plugin-view-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { CommandRegistry } from '@theia/core/lib/common/command';
import { MenuModelRegistry } from '@theia/core/lib/common/menu';
import { QuickViewService } from '@theia/core/lib/browser/quick-view-service';
import { Emitter } from '@theia/core/lib/common/event';
import { ContextKeyService } from '@theia/core/lib/browser/context-key-service';

export const PLUGIN_VIEW_FACTORY_ID = 'plugin-view';
export const PLUGIN_VIEW_CONTAINER_FACTORY_ID = 'plugin-view-container';
Expand Down Expand Up @@ -70,6 +71,9 @@ export class PluginViewRegistry implements FrontendApplicationContribution {
@inject(QuickViewService)
protected readonly quickView: QuickViewService;

@inject(ContextKeyService)
protected readonly contextKeyService: ContextKeyService;

protected readonly onDidExpandViewEmitter = new Emitter<string>();
readonly onDidExpandView = this.onDidExpandViewEmitter.event;

Expand Down Expand Up @@ -105,6 +109,48 @@ export class PluginViewRegistry implements FrontendApplicationContribution {
iconClass: 'theia-plugin-test-tab-icon',
closeable: true
});
this.contextKeyService.onDidChange(e => {
for (const [, view] of this.views.values()) {
if (view.when === undefined) {
continue;
}
if (e.affects(new Set([view.when]))) {
this.updateViewVisibility(view.id);
}
}
});
}

protected async updateViewVisibility(viewId: string): Promise<void> {
const viewInfo = this.views.get(viewId);
if (!viewInfo) {
return;
}
const [viewContainerId] = viewInfo;
const viewContainer = await this.getPluginViewContainer(viewContainerId);
if (!viewContainer) {
return;
}
const widget = await this.getView(viewId);
if (!widget) {
return;
}
const part = viewContainer.getPartFor(widget);
if (!part) {
return;
}
widget.updateViewVisibility(() =>
part.setHidden(!this.isViewVisible(viewId))
);
}

protected isViewVisible(viewId: string): boolean {
const viewInfo = this.views.get(viewId);
if (!viewInfo) {
return false;
}
const [, view] = viewInfo;
return view.when === undefined || this.contextKeyService.match(view.when);
}

registerViewContainer(location: string, viewContainer: ViewContainer): void {
Expand Down Expand Up @@ -255,11 +301,15 @@ export class PluginViewRegistry implements FrontendApplicationContribution {
const widget = await this.widgetManager.getOrCreateWidget<PluginViewWidget>(PLUGIN_VIEW_FACTORY_ID, identifier);
if (containerWidget.getTrackableWidgets().indexOf(widget) === -1) {
containerWidget.addWidget(widget, {
initiallyCollapsed: !!containerWidget.getParts().length
initiallyCollapsed: !!containerWidget.getParts().length,
initiallyHidden: !this.isViewVisible(viewId)
});
}
const part = containerWidget.getPartFor(widget);
if (part) {
// if a view is explicilty hidden then suppress updating visibility based on `when` closure
part.onVisibilityChanged(() => widget.suppressUpdateViewVisibility = part.isHidden);

const tryFireOnDidExpandView = () => {
if (!part.collapsed && part.isVisible) {
toFire.dispose();
Expand All @@ -275,9 +325,21 @@ export class PluginViewRegistry implements FrontendApplicationContribution {
}
}

protected getPluginViewContainer(viewContainerId: string): Promise<ViewContainerWidget | undefined> {
protected async getPluginViewContainer(viewContainerId: string): Promise<ViewContainerWidget | undefined> {
if (viewContainerId === 'explorer') {
return this.widgetManager.getWidget<ViewContainerWidget>(EXPLORER_VIEW_CONTAINER_ID);
}
if (viewContainerId === 'scm') {
return this.widgetManager.getWidget<ViewContainerWidget>(SCM_VIEW_CONTAINER_ID);
}
if (viewContainerId === 'debug') {
const debug = await this.widgetManager.getWidget(DebugWidget.ID);
if (debug instanceof DebugWidget) {
return debug['sessionWidget']['viewContainer'];
}
}
const identifier = this.toViewContainerIdentifier(viewContainerId);
return this.widgetManager.getWidget(PLUGIN_VIEW_CONTAINER_FACTORY_ID, identifier);
return this.widgetManager.getWidget<ViewContainerWidget>(PLUGIN_VIEW_CONTAINER_FACTORY_ID, identifier);
}

async initWidgets(): Promise<void> {
Expand Down
18 changes: 18 additions & 0 deletions packages/plugin-ext/src/main/browser/view/plugin-view-widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,24 @@ export class PluginViewWidget extends Panel implements StatefulWidget {
}
}

protected _suppressUpdateViewVisibility = false;
set suppressUpdateViewVisibility(suppressUpdateViewVisibility: boolean) {
this._suppressUpdateViewVisibility = !this.updatingViewVisibility && suppressUpdateViewVisibility;
}

protected updatingViewVisibility = false;
updateViewVisibility(cb: () => void): void {
if (this._suppressUpdateViewVisibility) {
return;
}
try {
this.updatingViewVisibility = true;
cb();
} finally {
this.updatingViewVisibility = false;
}
}

}
export namespace PluginViewWidget {
export interface State {
Expand Down