diff --git a/packages/debug/src/browser/debug-frontend-module.ts b/packages/debug/src/browser/debug-frontend-module.ts index 431eb7ee07705..82d2c277d3f2d 100644 --- a/packages/debug/src/browser/debug-frontend-module.ts +++ b/packages/debug/src/browser/debug-frontend-module.ts @@ -57,6 +57,8 @@ import { MonacoEditorService } from '@theia/monaco/lib/browser/monaco-editor-ser import { DebugBreakpointWidget } from './editor/debug-breakpoint-widget'; import { DebugInlineValueDecorator } from './editor/debug-inline-value-decorator'; import { JsonSchemaContribution } from '@theia/core/lib/browser/json-schema-store'; +import { TabBarDecorator } from '@theia/core/lib/browser/shell/tab-bar-decorator'; +import { DebugTabBarDecorator, DebugSessionManagerGetter } from './debug-tab-bar-decorator'; export default new ContainerModule((bind: interfaces.Bind) => { bind(DebugCallStackItemTypeKey).toDynamicValue(({ container }) => @@ -116,4 +118,8 @@ export default new ContainerModule((bind: interfaces.Bind) => { bindLaunchPreferences(bind); bind(DebugWatchManager).toSelf().inSingletonScope(); + bind(FrontendApplicationContribution).toService(DebugTabBarDecorator); + bind(DebugTabBarDecorator).toSelf().inSingletonScope(); + bind(DebugSessionManagerGetter).toDynamicValue(ctx => () => ctx.container.get(DebugSessionManager)).inSingletonScope(); + bind(TabBarDecorator).toService(DebugTabBarDecorator); }); diff --git a/packages/debug/src/browser/debug-tab-bar-decorator.ts b/packages/debug/src/browser/debug-tab-bar-decorator.ts new file mode 100644 index 0000000000000..9b9cc87326a83 --- /dev/null +++ b/packages/debug/src/browser/debug-tab-bar-decorator.ts @@ -0,0 +1,62 @@ +/******************************************************************************** + * Copyright (C) 2020 Ericsson and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + ********************************************************************************/ + +import { injectable, inject } from 'inversify'; +import { DebugSessionManager } from './debug-session-manager'; +import { DebugWidget } from './view/debug-widget'; +import { Emitter, Event } from '@theia/core/lib/common/event'; +import { TabBarDecorator } from '@theia/core/lib/browser/shell/tab-bar-decorator'; +import { FrontendApplication, FrontendApplicationContribution, Title, Widget } from '@theia/core/lib/browser'; +import { WidgetDecoration } from '@theia/core/lib/browser/widget-decoration'; +import { DisposableCollection } from '@theia/core/lib/common'; + +export const DebugSessionManagerGetter = Symbol.for('DebugSessionManagerGetter'); +export type DebugSessionManagerGetter = () => DebugSessionManager; + +@injectable() +export class DebugTabBarDecorator implements TabBarDecorator, FrontendApplicationContribution { + readonly id = 'theia-debug-tabbar-decorator'; + + protected readonly emitter = new Emitter(); + protected toDispose = new DisposableCollection(); + + @inject(DebugSessionManagerGetter) + protected readonly debugSessionManager: DebugSessionManagerGetter; + + onStart(app: FrontendApplication): void { + this.toDispose.pushAll([ + this.debugSessionManager().onDidStartDebugSession(() => this.fireDidChangeDecorations()), + this.debugSessionManager().onDidDestroyDebugSession(() => this.fireDidChangeDecorations()) + ]); + } + + decorate(title: Title): WidgetDecoration.Data[] { + if (title.owner.id === DebugWidget.ID) { + const sessionCount = this.debugSessionManager().sessions.length; + return sessionCount > 0 ? [{ badge: sessionCount }] : []; + } else { + return []; + } + } + + get onDidChangeDecorations(): Event { + return this.emitter.event; + } + + protected fireDidChangeDecorations(): void { + this.emitter.fire(undefined); + } +}