From 3d17ad24b1337317b5f84c5b65006a81181b2776 Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Thu, 30 Apr 2020 13:32:10 +0000 Subject: [PATCH] fix #2234: activate another widget if an active widget gets closed support next/previous tab group commands support next/previous tab in group commands Signed-off-by: Anton Kosyakov --- .../browser/common-frontend-contribution.ts | 36 ++++++ .../src/browser/shell/application-shell.ts | 122 ++++++++++++++++-- 2 files changed, 144 insertions(+), 14 deletions(-) diff --git a/packages/core/src/browser/common-frontend-contribution.ts b/packages/core/src/browser/common-frontend-contribution.ts index 843541f66f4fe..dc2ca29cfbc13 100644 --- a/packages/core/src/browser/common-frontend-contribution.ts +++ b/packages/core/src/browser/common-frontend-contribution.ts @@ -133,6 +133,26 @@ export namespace CommonCommands { category: VIEW_CATEGORY, label: 'Switch to Previous Tab' }; + export const NEXT_TAB_IN_GROUP: Command = { + id: 'core.nextTabInGroup', + category: VIEW_CATEGORY, + label: 'Switch to Next Tab in Group' + }; + export const PREVIOUS_TAB_IN_GROUP: Command = { + id: 'core.previousTabInGroup', + category: VIEW_CATEGORY, + label: 'Switch to Previous Tab in Group' + }; + export const NEXT_TAB_GROUP: Command = { + id: 'core.nextTabGroup', + category: VIEW_CATEGORY, + label: 'Switch to Next Tab Group' + }; + export const PREVIOUS_TAB_GROUP: Command = { + id: 'core.previousTabBar', + category: VIEW_CATEGORY, + label: 'Switch to Previous Tab Group' + }; export const CLOSE_TAB: Command = { id: 'core.close.tab', category: VIEW_CATEGORY, @@ -529,6 +549,22 @@ export class CommonFrontendContribution implements FrontendApplicationContributi isEnabled: () => this.shell.currentTabBar !== undefined, execute: () => this.shell.activatePreviousTab() }); + commandRegistry.registerCommand(CommonCommands.NEXT_TAB_IN_GROUP, { + isEnabled: () => this.shell.nextTabIndexInTabBar() !== -1, + execute: () => this.shell.activateNextTabInTabBar() + }); + commandRegistry.registerCommand(CommonCommands.PREVIOUS_TAB_IN_GROUP, { + isEnabled: () => this.shell.previousTabIndexInTabBar() !== -1, + execute: () => this.shell.activatePreviousTabInTabBar() + }); + commandRegistry.registerCommand(CommonCommands.NEXT_TAB_GROUP, { + isEnabled: () => this.shell.nextTabBar() !== undefined, + execute: () => this.shell.activateNextTabBar() + }); + commandRegistry.registerCommand(CommonCommands.PREVIOUS_TAB_GROUP, { + isEnabled: () => this.shell.previousTabBar() !== undefined, + execute: () => this.shell.activatePreviousTabBar() + }); commandRegistry.registerCommand(CommonCommands.CLOSE_TAB, { isEnabled: (event?: Event) => { const tabBar = this.findTabBar(event); diff --git a/packages/core/src/browser/shell/application-shell.ts b/packages/core/src/browser/shell/application-shell.ts index b35d70970de16..719bde33ef7c2 100644 --- a/packages/core/src/browser/shell/application-shell.ts +++ b/packages/core/src/browser/shell/application-shell.ts @@ -877,6 +877,8 @@ export class ApplicationShell extends Widget { */ readonly activeChanged = new Signal>(this); + protected readonly toDisposeOnActiveChanged = new DisposableCollection(); + /** * Handle a change to the active widget. */ @@ -914,6 +916,28 @@ export class ApplicationShell extends Widget { } // Set the z-index so elements with `position: fixed` contained in the active widget are displayed correctly this.setZIndex(newValue.node, '1'); + + // activate another widget if an active widget gets closed + const onCloseRequest = newValue['onCloseRequest']; + newValue['onCloseRequest'] = msg => { + const currentTabBar = this.currentTabBar; + if (currentTabBar) { + const recentlyUsedInTabBar = currentTabBar['_previousTitle'] as TabBar['currentTitle']; + if (recentlyUsedInTabBar && recentlyUsedInTabBar.owner !== newValue) { + currentTabBar.currentIndex = ArrayExt.firstIndexOf(currentTabBar.titles, recentlyUsedInTabBar); + if (currentTabBar.currentTitle) { + currentTabBar.currentTitle.owner.activate(); + } + } else if (!this.activateNextTabInTabBar(currentTabBar)) { + if (!this.activatePreviousTabBar(currentTabBar)) { + this.activateNextTabBar(currentTabBar); + } + } + } + newValue['onCloseRequest'] = onCloseRequest; + newValue['onCloseRequest'](msg); + }; + this.toDisposeOnActiveChanged.push(Disposable.create(() => newValue['onCloseRequest'] = onCloseRequest)); } this.activeChanged.emit(args); this.onDidChangeActiveWidgetEmitter.fire(args); @@ -1502,7 +1526,33 @@ export class ApplicationShell extends Widget { /* * Activate the next tab in the current tab bar. */ - activateNextTab(): void { + activateNextTabInTabBar(current: TabBar | undefined = this.currentTabBar): boolean { + const index = this.nextTabIndexInTabBar(current); + if (!current || index === -1) { + return false; + } + current.currentIndex = index; + if (current.currentTitle) { + current.currentTitle.owner.activate(); + } + return true; + } + + nextTabIndexInTabBar(current: TabBar | undefined = this.currentTabBar): number { + if (!current || current.titles.length <= 1) { + return -1; + } + const index = current.currentIndex; + if (index === -1) { + return -1; + } + if (index < current.titles.length - 1) { + return index + 1; + } + return 0; + } + + activateNextTab(): boolean { const current = this.currentTabBar; if (current) { const ci = current.currentIndex; @@ -1512,21 +1562,31 @@ export class ApplicationShell extends Widget { if (current.currentTitle) { current.currentTitle.owner.activate(); } + return true; } else if (ci === current.titles.length - 1) { - const nextBar = this.nextTabBar(current); - nextBar.currentIndex = 0; - if (nextBar.currentTitle) { - nextBar.currentTitle.owner.activate(); - } + return this.activateNextTabBar(current); } } } + return false; + } + + activateNextTabBar(current: TabBar | undefined = this.currentTabBar): boolean { + const nextBar = this.nextTabBar(current); + if (nextBar) { + nextBar.currentIndex = 0; + if (nextBar.currentTitle) { + nextBar.currentTitle.owner.activate(); + } + return true; + } + return false; } /** * Return the tab bar next to the given tab bar; return the given tab bar if there is no adjacent one. */ - private nextTabBar(current: TabBar): TabBar { + nextTabBar(current: TabBar | undefined = this.currentTabBar): TabBar | undefined { let bars = toArray(this.bottomPanel.tabBars()); let len = bars.length; let ci = ArrayExt.firstIndexOf(bars, current); @@ -1547,6 +1607,32 @@ export class ApplicationShell extends Widget { /* * Activate the previous tab in the current tab bar. */ + activatePreviousTabInTabBar(current: TabBar | undefined = this.currentTabBar): boolean { + const index = this.previousTabIndexInTabBar(current); + if (!current || index === -1) { + return false; + } + current.currentIndex = index; + if (current.currentTitle) { + current.currentTitle.owner.activate(); + } + return true; + } + + previousTabIndexInTabBar(current: TabBar | undefined = this.currentTabBar): number { + if (!current || current.titles.length <= 1) { + return -1; + } + const index = current.currentIndex; + if (index === -1) { + return -1; + } + if (index > 0) { + return index - 1; + } + return current.titles.length - 1; + } + activatePreviousTab(): void { const current = this.currentTabBar; if (current) { @@ -1558,21 +1644,29 @@ export class ApplicationShell extends Widget { current.currentTitle.owner.activate(); } } else if (ci === 0) { - const prevBar = this.previousTabBar(current); - const len = prevBar.titles.length; - prevBar.currentIndex = len - 1; - if (prevBar.currentTitle) { - prevBar.currentTitle.owner.activate(); - } + this.activatePreviousTabBar(current); } } } } + activatePreviousTabBar(current: TabBar | undefined = this.currentTabBar): boolean { + const prevBar = this.previousTabBar(current); + if (!prevBar) { + return false; + } + const len = prevBar.titles.length; + prevBar.currentIndex = len - 1; + if (prevBar.currentTitle) { + prevBar.currentTitle.owner.activate(); + } + return true; + } + /** * Return the tab bar previous to the given tab bar; return the given tab bar if there is no adjacent one. */ - private previousTabBar(current: TabBar): TabBar { + previousTabBar(current: TabBar | undefined = this.currentTabBar): TabBar | undefined { const bars = toArray(this.mainPanel.tabBars()); const len = bars.length; const ci = ArrayExt.firstIndexOf(bars, current);