@theia/core
Version:
Theia is a cloud & desktop IDE framework implemented in TypeScript.
69 lines (61 loc) • 2.81 kB
text/typescript
// *****************************************************************************
// Copyright (C) 2026 JuliaHub, Inc. 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-only WITH Classpath-exception-2.0
// *****************************************************************************
import { find } from '@lumino/algorithm';
import { DockPanel, TabBar, Widget } from '@lumino/widgets';
import { Disposable, DisposableCollection } from '../../common';
/**
* Detects when a widget is moved between the tab-bars of its enclosing {@link DockPanel} and
* notifies a callback with the previous and current tab-bar. Call {@link check} from the host
* widget's `onAfterAttach`.
*/
export class TabBarTracker implements Disposable {
protected currentTabBar: TabBar<Widget> | undefined;
protected isDisposed = false;
protected readonly toDisposeOnTabBarChange = new DisposableCollection();
constructor(
protected readonly widget: Widget,
protected readonly onTabBarChange: (oldTabBar?: TabBar<Widget>, newTabBar?: TabBar<Widget>) => void
) { }
check(): void {
if (this.isDisposed) {
return;
}
const parent = this.widget.parent;
if (parent instanceof DockPanel) {
const newTabBar = find(parent.tabBars(), tabBar => !!tabBar.titles.find(title => title === this.widget.title));
if (this.currentTabBar !== newTabBar) {
this.toDisposeOnTabBarChange.dispose();
const listener = () => this.check();
parent.layoutModified.connect(listener);
this.toDisposeOnTabBarChange.push(Disposable.create(() => parent.layoutModified.disconnect(listener)));
const last = this.currentTabBar;
this.currentTabBar = newTabBar;
this.onTabBarChange(last, newTabBar);
}
}
}
/**
* Forgets the current tab-bar so that the next {@link check} reports it again as
* `(undefined, currentTabBar)`. Listeners on the enclosing panel stay connected.
*/
reset(): void {
this.currentTabBar = undefined;
}
dispose(): void {
this.isDisposed = true;
this.toDisposeOnTabBarChange.dispose();
}
}