Skip to content

Commit

Permalink
Clean up commands
Browse files Browse the repository at this point in the history
  • Loading branch information
kenneth-marut-work committed Jul 14, 2021
1 parent 9090c55 commit 98a21a7
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 76 deletions.
29 changes: 29 additions & 0 deletions packages/core/src/browser/shell/application-shell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1400,6 +1400,29 @@ export class ApplicationShell extends Widget {
}
}

saveTabs(tabBarOrArea: TabBar<Widget> | ApplicationShell.Area,
filter?: (title: Title<Widget>, index: number) => boolean): void {
if (tabBarOrArea === 'main') {
this.mainAreaTabBars.forEach(tb => this.saveTabs(tb, filter));
} else if (tabBarOrArea === 'bottom') {
this.bottomAreaTabBars.forEach(tb => this.saveTabs(tb, filter));
} else if (typeof tabBarOrArea === 'string') {
const tabBar = this.getTabBarFor(tabBarOrArea);
if (tabBar) {
this.saveTabs(tabBar, filter);
}
} else if (tabBarOrArea) {
const titles = toArray(tabBarOrArea.titles);
for (let i = 0; i < titles.length; i++) {
if (filter === undefined || filter(titles[i], i)) {
const widget = titles[i].owner;
const saveable = Saveable.get(widget);
saveable?.save();
}
}
}
}

async closeWidget(id: string, options?: ApplicationShell.CloseOptions): Promise<Widget | undefined> {
// TODO handle save for composite widgets, i.e. the preference widget has 2 editors
const stack = this.toTrackedStack(id);
Expand Down Expand Up @@ -1811,6 +1834,12 @@ export namespace ApplicationShell {
return area === 'left' || area === 'right' || area === 'bottom';
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function isValidArea(area?: any): area is ApplicationShell.Area {
const areas = ['main', 'top', 'left', 'right', 'bottom'];
return (area !== undefined && typeof area === 'string' && areas.includes(area));
}

/**
* General options for the application shell. These are passed on construction and can be modified
* through dependency injection (`ApplicationShellOptions` symbol).
Expand Down
28 changes: 14 additions & 14 deletions packages/navigator/src/browser/navigator-contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ import {
SHELL_TABBAR_CONTEXT_MENU,
Widget,
NavigatableWidget,
Saveable,
ApplicationShell,
TabBar,
Title
} from '@theia/core/lib/browser';
import { FileDownloadCommands } from '@theia/filesystem/lib/browser/download/file-download-command-contribution';
import {
Expand Down Expand Up @@ -377,22 +379,20 @@ export class FileNavigatorContribution extends AbstractViewContribution<FileNavi
isEnabled: widget => this.withOpenEditorsWidget(widget, () => !!this.editorWidgets.length),
isVisible: widget => this.withOpenEditorsWidget(widget, () => !!this.editorWidgets.length)
});
registry.registerCommand(OpenEditorsCommands.CLOSE_ALL_IN_GROUP, {
execute: async (id): Promise<void> => {
const openEditorsWidget = await this.widgetManager.getOrCreateWidget<OpenEditorsWidget>(OpenEditorsWidget.ID);
const widgets = openEditorsWidget.getEditorWidgetsByGroup(id);
widgets?.forEach(widget => widget.close());

const filterEditorWidgets = (title: Title<Widget>) => {
const { owner } = title;
return NavigatableWidget.is(owner);
};
registry.registerCommand(OpenEditorsCommands.CLOSE_ALL_EDITORS_IN_GROUP_FROM_ICON, {
execute: (tabBarOrArea: ApplicationShell.Area | TabBar<Widget>): void => {
this.shell.closeTabs(tabBarOrArea, filterEditorWidgets);
},
isVisible: () => false
});
registry.registerCommand(OpenEditorsCommands.SAVE_ALL_IN_GROUP, {
execute: async (id): Promise<void> => {
const openEditorsWidget = await this.widgetManager.getOrCreateWidget<OpenEditorsWidget>(OpenEditorsWidget.ID);
const widgets = openEditorsWidget.getEditorWidgetsByGroup(id);
widgets?.forEach(widget => {
const saveable = Saveable.get(widget);
saveable?.save();
});
registry.registerCommand(OpenEditorsCommands.SAVE_ALL_IN_GROUP_FROM_ICON, {
execute: (tabBarOrArea: ApplicationShell.Area | TabBar<Widget>) => {
this.shell.saveTabs(tabBarOrArea, filterEditorWidgets);
},
isVisible: () => false
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,30 @@ import { Command } from '@theia/core/lib/common';

export namespace OpenEditorsCommands {
export const CLOSE_ALL_TABS_FROM_TOOLBAR: Command = {
id: 'navigator.close.all.editors',
id: 'navigator.close.all.editors.toolbar',
category: 'File',
label: 'Close All Editors',
iconClass: 'codicon codicon-close-all'
};

export const SAVE_ALL_TABS_FROM_TOOLBAR: Command = {
id: 'navigator.save.all.editors',
id: 'navigator.save.all.editors.toolbar',
category: 'File',
label: 'Save All Editors',
iconClass: 'codicon codicon-save-all'
};

export const SAVE_ALL_IN_GROUP: Command = {
id: 'navigator.save.all.in.ground',
category: 'File',
label: 'Save All in Group',
iconClass: 'codicon codicon-save-all'
export const CLOSE_ALL_EDITORS_IN_GROUP_FROM_ICON: Command = {
id: 'navigator.close.all.in.area.icon',
category: 'View',
label: 'Close Group',
iconClass: 'codicon codicon-close-all'
};

export const CLOSE_ALL_IN_GROUP: Command = {
id: 'navigator.close.all.in.group',
export const SAVE_ALL_IN_GROUP_FROM_ICON: Command = {
id: 'navigator.save.all.in.area.icon',
category: 'File',
label: 'Close Group',
iconClass: 'codicon codicon-close-all'
label: 'Save All in Group',
iconClass: 'codicon codicon-save-all'
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ import {
SelectableTreeNode,
TreeNode,
Widget,
ExpandableTreeNode
ExpandableTreeNode,
TabBar
} from '@theia/core/lib/browser';
import { WorkspaceService } from '@theia/workspace/lib/browser';
import debounce = require('@theia/core/shared/lodash.debounce');
Expand All @@ -51,7 +52,7 @@ export class OpenEditorsModel extends FileTreeModel {

protected toDisposeOnPreviewWidgetReplaced = new DisposableCollection();
// Returns the collection of editors belonging to a tabbar group in the main area
protected _editorWidgetsByGroup = new Map<number, NavigatableWidget[]>();
protected _editorWidgetsByGroup = new Map<number, { widgets: NavigatableWidget[], tabbar: TabBar<Widget> }>();

// Returns the collection of editors belonging to an area grouping (main, left, right bottom)
protected _editorWidgetsByArea = new Map<ApplicationShell.Area, NavigatableWidget[]>();
Expand All @@ -65,12 +66,8 @@ export class OpenEditorsModel extends FileTreeModel {
return editorWidgets;
}

getEditorWidgetsByGroup(id: ApplicationShell.Area | number): NavigatableWidget[] | undefined {
const idAsNum = Number(id);
if (!isNaN(idAsNum)) {
return this._editorWidgetsByGroup.get(idAsNum);
}
return this._editorWidgetsByArea.get(id as ApplicationShell.Area);
getTabBarForGroup(id: number): TabBar<Widget> | undefined {
return this._editorWidgetsByGroup.get(id)?.tabbar;
}

@postConstruct()
Expand Down Expand Up @@ -163,7 +160,7 @@ export class OpenEditorsModel extends FileTreeModel {
widgets.push(owner);
}
});
this._editorWidgetsByGroup.set(groupNumber, widgets);
this._editorWidgetsByGroup.set(groupNumber, { widgets, tabbar });
});
}
return widgetGroupMap;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@ import {
NavigatableWidget,
NodeProps,
Saveable,
TabBar,
TreeDecoratorService,
TreeModel,
TreeNode,
TreeProps,
TreeWidget,
TREE_NODE_CONTENT_CLASS,
Widget,
} from '@theia/core/lib/browser';
import { OpenEditorNode, OpenEditorsModel } from './navigator-open-editors-tree-model';
import { createFileTreeContainer, FileTreeModel, FileTreeWidget } from '@theia/filesystem/lib/browser';
Expand Down Expand Up @@ -96,10 +98,6 @@ export class OpenEditorsWidget extends FileTreeWidget {
return this.model.editorWidgets;
}

getEditorWidgetsByGroup(id: ApplicationShell.Area | number): NavigatableWidget[] | undefined {
return this.model.getEditorWidgetsByGroup(id);
}

// eslint-disable-next-line no-null/no-null
protected activeTreeNodePrefixElement: string | undefined | null;

Expand Down Expand Up @@ -146,18 +144,18 @@ export class OpenEditorsWidget extends FileTreeWidget {
return (<div className='open-editors-inline-actions-container'>
<div className='open-editors-inline-action'>
<a className='codicon codicon-save-all'
title='Save all in Group'
title={OpenEditorsCommands.SAVE_ALL_IN_GROUP_FROM_ICON.label}
onClick={this.handleGroupActionIconClicked}
data-id={node.id}
id={OpenEditorsCommands.SAVE_ALL_IN_GROUP.id}
id={OpenEditorsCommands.SAVE_ALL_IN_GROUP_FROM_ICON.id}
/>
</div>
<div className='open-editors-inline-action' >
<a className='codicon codicon-close-all'
title='Close Group'
title={OpenEditorsCommands.CLOSE_ALL_EDITORS_IN_GROUP_FROM_ICON.label}
onClick={this.handleGroupActionIconClicked}
data-id={node.id}
id={OpenEditorsCommands.CLOSE_ALL_IN_GROUP.id}
id={OpenEditorsCommands.CLOSE_ALL_EDITORS_IN_GROUP_FROM_ICON.id}
/>
</div>
</div>
Expand All @@ -170,9 +168,27 @@ export class OpenEditorsWidget extends FileTreeWidget {
const groupName = e.currentTarget.getAttribute('data-id');
const command = e.currentTarget.id;
if (groupName && command) {
const group = groupName.split(':').pop();
return this.commandService.executeCommand(command, group);
const groupFromTarget: string | number | undefined = groupName.split(':').pop();
const areaOrTabBar = this.sanitizeInputFromClickHandler(groupFromTarget);
if (areaOrTabBar) {
return this.commandService.executeCommand(command, areaOrTabBar);
}
}
}

protected sanitizeInputFromClickHandler(groupFromTarget?: string): ApplicationShell.Area | TabBar<Widget> | undefined {
let areaOrTabBar: ApplicationShell.Area | TabBar<Widget> | undefined;
if (groupFromTarget) {
if (ApplicationShell.isValidArea(groupFromTarget)) {
areaOrTabBar = groupFromTarget;
} else {
const groupAsNum = parseInt(groupFromTarget);
if (!isNaN(groupAsNum)) {
areaOrTabBar = this.model.getTabBarForGroup(groupAsNum);
}
}
}
return areaOrTabBar;
}

protected renderPrefixIcon(node: OpenEditorNode): React.ReactNode {
Expand Down
28 changes: 14 additions & 14 deletions packages/navigator/src/browser/open-editors-widget/open-editors.css
Original file line number Diff line number Diff line change
Expand Up @@ -23,50 +23,50 @@
font-size: var(--theia-ui-font-size0);
}

.open-editors-node-row .open-editors-prefix-icon-container {
.theia-open-editors-widget .open-editors-node-row .open-editors-prefix-icon-container {
min-width: var(--theia-open-editors-icon-width);
}

.open-editors-node-row .open-editors-prefix-icon.dirty,
.open-editors-node-row.dirty:hover .open-editors-prefix-icon.dirty {
.theia-open-editors-widget .open-editors-node-row .open-editors-prefix-icon.dirty,
.theia-open-editors-widget .open-editors-node-row.dirty:hover .open-editors-prefix-icon.dirty {
display: none;
}

.open-editors-node-row.dirty .open-editors-prefix-icon.dirty {
.theia-open-editors-widget .open-editors-node-row.dirty .open-editors-prefix-icon.dirty {
display: block;
}

.open-editors-node-row .open-editors-prefix-icon.close {
.theia-open-editors-widget .open-editors-node-row .open-editors-prefix-icon.close {
display: none;
}

.open-editors-node-row:hover .open-editors-prefix-icon.close {
.theia-open-editors-widget .open-editors-node-row:hover .open-editors-prefix-icon.close {
display: block;
}

.open-editors-node-row.group-node,
.open-editors-node-row.area-node {
.theia-open-editors-widget .open-editors-node-row.group-node,
.theia-open-editors-widget .open-editors-node-row.area-node {
font-weight: 700;
text-transform: uppercase;
font-size: var(--theia-ui-font-size0);
}

.open-editors-node-row.area-node {
.theia-open-editors-widget .open-editors-node-row.area-node {
font-style: italic;
}

.open-editors-inline-actions-container {
.theia-open-editors-widget .open-editors-inline-actions-container {
display: flex;
justify-content: flex-end;
margin-left: 3px;
min-height: 16px;
}

.open-editors-inline-action a {
.theia-open-editors-widget .open-editors-inline-action a {
color: var(--theia-icon-foreground);
}

.open-editors-inline-action {
.theia-open-editors-widget .open-editors-inline-action {
padding: 0px 3px;
font-size: var(--theia-ui-font-size1);
margin: 0 2px;
Expand All @@ -75,10 +75,10 @@
align-items: center;
}

.open-editors-node-row .open-editors-inline-actions-container {
.theia-open-editors-widget .open-editors-node-row .open-editors-inline-actions-container {
visibility: hidden;
}

.open-editors-node-row:hover .open-editors-inline-actions-container {
.theia-open-editors-widget .open-editors-node-row:hover .open-editors-inline-actions-container {
visibility: visible;
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ import {
open,
OpenerService,
QuickInputService,
Saveable
Saveable,
TabBar,
Title,
Widget
} from '@theia/core/lib/browser';
import { ContextKeyService } from '@theia/core/lib/browser/context-key-service';
import { ApplicationShellMouseTracker } from '@theia/core/lib/browser/shell/application-shell-mouse-tracker';
Expand Down Expand Up @@ -287,25 +290,41 @@ export class PluginVscodeCommandsContribution implements CommandContribution {
}
}
});
commands.registerCommand({ id: 'workbench.action.closeEditorsInGroup' }, {
execute: (uri?: monaco.Uri) => {
let editor = this.editorManager.currentEditor || this.shell.currentWidget;
if (uri) {
const uriString = uri.toString();
editor = this.editorManager.all.find(e => {
const resourceUri = e.getResourceUri();
return (resourceUri && resourceUri.toString()) === uriString;
});
}
if (editor) {
const tabBar = this.shell.getTabBarFor(editor);
if (tabBar) {
this.shell.closeTabs(tabBar,
({ owner }) => this.codeEditorWidgetUtil.is(owner)
);
}

const performActionOnGroup = (
cb: (
tabBarOrArea: TabBar<Widget> | ApplicationShell.Area,
filter?: ((title: Title<Widget>, index: number) => boolean) | undefined
) => void,
uri?: monaco.Uri
): void => {
let editor = this.editorManager.currentEditor || this.shell.currentWidget;
if (uri) {
const uriString = uri.toString();
editor = this.editorManager.all.find(e => {
const resourceUri = e.getResourceUri();
return (resourceUri && resourceUri.toString()) === uriString;
});
}
if (editor) {
const tabBar = this.shell.getTabBarFor(editor);
if (tabBar) {
cb(tabBar, ({ owner }) => this.codeEditorWidgetUtil.is(owner));
}
}
};

commands.registerCommand({
id: 'workbench.action.closeEditorsInGroup',
label: 'Close All Editors in Group'
}, {
execute: (uri?: monaco.Uri) => performActionOnGroup(this.shell.closeTabs, uri)
});
commands.registerCommand({
id: 'workbench.files.saveAllInGroup',
label: 'Save All in Group'
}, {
execute: (uri?: monaco.Uri) => performActionOnGroup(this.shell.saveTabs, uri)
});
commands.registerCommand({ id: 'workbench.action.closeEditorsInOtherGroups' }, {
execute: () => {
Expand Down

0 comments on commit 98a21a7

Please sign in to comment.