提交 09c278ee 编写于 作者: B Benjamin Pasero

grid - show close action for empty groups

上级 e2fb5f19
......@@ -32,7 +32,7 @@ import {
NavigateBetweenGroupsAction, FocusActiveGroupAction, FocusFirstGroupAction, FocusSecondGroupAction, FocusThirdGroupAction, EvenGroupWidthsAction, MaximizeGroupAction, MinimizeOtherGroupsAction, FocusPreviousGroup, FocusNextGroup, ShowEditorsInGroupOneAction,
toEditorQuickOpenEntry, CloseLeftEditorsInGroupAction, OpenNextEditor, OpenPreviousEditor, NavigateBackwardsAction, NavigateForwardAction, NavigateLastAction, ReopenClosedEditorAction, OpenPreviousRecentlyUsedEditorInGroupAction,
OpenPreviousEditorFromHistoryAction, ShowAllEditorsAction, ClearEditorHistoryAction, ShowEditorsInGroupTwoAction, MoveEditorRightInGroupAction, OpenNextEditorInGroup, OpenPreviousEditorInGroup, OpenNextRecentlyUsedEditorAction, OpenPreviousRecentlyUsedEditorAction,
ShowEditorsInGroupThreeAction, FocusLastEditorInStackAction, OpenNextRecentlyUsedEditorInGroupAction, MoveEditorToPreviousGroupAction, MoveEditorToNextGroupAction, MoveEditorToFirstGroupAction, MoveEditorToSecondGroupAction, MoveEditorToThirdGroupAction, MoveEditorLeftInGroupAction, ClearRecentFilesAction, OpenLastEditorInGroup, SplitEditorGroupHorizontalAction, SplitEditorGroupVerticalAction
ShowEditorsInGroupThreeAction, FocusLastEditorInStackAction, OpenNextRecentlyUsedEditorInGroupAction, MoveEditorToPreviousGroupAction, MoveEditorToNextGroupAction, MoveEditorToFirstGroupAction, MoveEditorToSecondGroupAction, MoveEditorToThirdGroupAction, MoveEditorLeftInGroupAction, ClearRecentFilesAction, OpenLastEditorInGroup, SplitEditorGroupHorizontalAction, SplitEditorGroupVerticalAction, RemoveActiveEditorGroupAction
} from 'vs/workbench/browser/parts/editor/editorActions';
import * as editorCommands from 'vs/workbench/browser/parts/editor/editorCommands';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
......@@ -42,7 +42,7 @@ import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { isMacintosh } from 'vs/base/common/platform';
import { GroupOnePicker, GroupTwoPicker, GroupThreePicker, AllEditorsPicker } from 'vs/workbench/browser/parts/editor/editorPicker';
import { Schemas } from 'vs/base/common/network';
import { GridOpenEditorsAction, GridCloseActiveEditorAction, GridRemoveActiveGroupAction, GridOpenOneEditorAction, GridOpenOneEditorSideBySideAction, ResetGridEditorAction } from 'vs/workbench/browser/parts/editor2/nextEditorActions';
import { GridOpenEditorsAction, GridCloseActiveEditorAction, GridOpenOneEditorAction, GridOpenOneEditorSideBySideAction, ResetGridEditorAction } from 'vs/workbench/browser/parts/editor2/nextEditorActions';
// Register String Editor
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
......@@ -442,8 +442,9 @@ const gridCategory = nls.localize('grid', "Grid");
registry.registerWorkbenchAction(new SyncActionDescriptor(ResetGridEditorAction, ResetGridEditorAction.ID, ResetGridEditorAction.LABEL), 'Grid: Reset Grid', gridCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(GridOpenEditorsAction, GridOpenEditorsAction.ID, GridOpenEditorsAction.LABEL), 'Grid: Open Some Editors', gridCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(GridCloseActiveEditorAction, GridCloseActiveEditorAction.ID, GridCloseActiveEditorAction.LABEL), 'Grid: Close Active Editor', gridCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(GridRemoveActiveGroupAction, GridRemoveActiveGroupAction.ID, GridRemoveActiveGroupAction.LABEL), 'Grid: Remove Active Group', gridCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(RemoveActiveEditorGroupAction, RemoveActiveEditorGroupAction.ID, RemoveActiveEditorGroupAction.LABEL), 'Grid: Remove Active Editor Group', gridCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(GridOpenOneEditorAction, GridOpenOneEditorAction.ID, GridOpenOneEditorAction.LABEL), 'Grid: Open One Editor', gridCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(GridOpenOneEditorSideBySideAction, GridOpenOneEditorSideBySideAction.ID, GridOpenOneEditorSideBySideAction.LABEL), 'Grid: Open One Editor Side by Side', gridCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(SplitEditorGroupHorizontalAction, SplitEditorGroupHorizontalAction.ID, SplitEditorGroupHorizontalAction.LABEL), 'Grid: Split Horizontal', gridCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(SplitEditorGroupVerticalAction, SplitEditorGroupVerticalAction.ID, SplitEditorGroupVerticalAction.LABEL), 'Grid: Split Vertical', gridCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(SplitEditorGroupVerticalAction, SplitEditorGroupVerticalAction.ID, SplitEditorGroupVerticalAction.LABEL), 'Grid: Split Vertical', gridCategory);
\ No newline at end of file
......@@ -9,7 +9,7 @@ import * as nls from 'vs/nls';
import { Action } from 'vs/base/common/actions';
import { mixin } from 'vs/base/common/objects';
import { getCodeEditor } from 'vs/editor/browser/services/codeEditorService';
import { EditorInput, TextEditorOptions, EditorOptions, IEditorIdentifier, ActiveEditorMoveArguments, ActiveEditorMovePositioning, EditorCommands, ConfirmResult, IEditorCommandsContext } from 'vs/workbench/common/editor';
import { EditorInput, TextEditorOptions, EditorOptions, IEditorIdentifier, ActiveEditorMoveArguments, ActiveEditorMovePositioning, EditorCommands, ConfirmResult, IEditorCommandsContext, GroupIdentifier, groupFromContext } from 'vs/workbench/common/editor';
import { QuickOpenEntryGroup } from 'vs/base/parts/quickopen/browser/quickOpenModel';
import { EditorQuickOpenEntry, EditorQuickOpenEntryGroup, IEditorQuickOpenEntry, QuickOpenAction } from 'vs/workbench/browser/quickopen';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
......@@ -186,6 +186,30 @@ export class SplitEditorGroupHorizontalAction extends BaseSplitEditorGroupAction
}
}
export class RemoveActiveEditorGroupAction extends Action {
static readonly ID = 'workbench.action.removeActiveEditorGroup';
static readonly LABEL = nls.localize('removeActiveGroup', "Remove Active Editor Group");
constructor(
id: string,
label: string,
@INextEditorGroupsService private nextEditorGroupsService: INextEditorGroupsService
) {
super(id, label);
this.class = 'close-editor-group';
}
run(context?: GroupIdentifier): TPromise<any> {
const group = groupFromContext(context, this.nextEditorGroupsService);
this.nextEditorGroupsService.removeGroup(group);
return TPromise.as(void 0);
}
}
export class JoinTwoGroupsAction extends Action {
public static readonly ID = 'workbench.action.joinTwoGroups';
......
......@@ -3,6 +3,8 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/** Container */
.monaco-workbench > .part.editor > .content .editor-group-container {
height: 100%;
}
......@@ -27,6 +29,8 @@
outline-width: 0; /* no outline when editor part is empty */
}
/** Title */
.monaco-workbench > .part.editor > .content .editor-group-container > .title {
height: 35px;
display: flex;
......@@ -41,4 +45,38 @@
.monaco-workbench > .part.editor > .content .editor-group-container.empty > .title,
.monaco-workbench > .part.editor > .content .editor-group-container.empty > .editor-container {
display: none;
}
/** Toolbar */
.monaco-workbench > .part.editor > .content .editor-group-container > .editor-group-container-toolbar {
display: none;
opacity: 0.5;
}
.monaco-workbench > .part.editor > .content .editor-group-container.empty > .editor-group-container-toolbar {
display: block;
}
.monaco-workbench > .part.editor > .content .editor-group-container.empty.active > .editor-group-container-toolbar {
opacity: 1;
}
.monaco-workbench > .part.editor > .content .editor-group-container > .editor-group-container-toolbar .action-label {
display: block;
height: 35px;
line-height: 35px;
min-width: 28px;
background-size: 16px;
background-position: center center;
background-repeat: no-repeat;
}
.vs .monaco-workbench > .part.editor > .content .editor-group-container > .editor-group-container-toolbar .close-editor-group {
background-image: url('close.svg');
}
.vs-dark .monaco-workbench > .part.editor > .content .editor-group-container > .editor-group-container-toolbar .close-editor-group,
.hc-black .monaco-workbench > .part.editor > .content .editor-group-container > .editor-group-container-toolbar .close-editor-group {
background-image: url('close-inverse.svg');
}
\ No newline at end of file
......@@ -75,12 +75,12 @@
/* Actions */
.monaco-workbench .close-editor-action {
.monaco-workbench > .part.editor > .content .editor-group-container > .title .close-editor-action {
background: url('close.svg') center center no-repeat;
}
.vs-dark .monaco-workbench .close-editor-action,
.hc-black .monaco-workbench .close-editor-action {
.vs-dark .monaco-workbench > .part.editor > .content .editor-group-container > .title .close-editor-action,
.hc-black .monaco-workbench > .part.editor > .content .editor-group-container > .title .close-editor-action {
background: url('close-inverse.svg') center center no-repeat;
}
......
......@@ -160,26 +160,6 @@ export class GridCloseActiveEditorAction extends Action {
run(): TPromise<any> {
this.nextEditorGroupsService.activeGroup.closeEditor();
return TPromise.as(void 0);
}
}
export class GridRemoveActiveGroupAction extends Action {
static readonly ID = 'workbench.action.gridRemoveActiveGroup';
static readonly LABEL = localize('gridRemoveActiveGroup', "Remove Active Group");
constructor(
id: string,
label: string,
@INextEditorGroupsService private nextEditorGroupsService: INextEditorGroupsService
) {
super(id, label);
}
run(): TPromise<any> {
this.nextEditorGroupsService.removeGroup(this.nextEditorGroupsService.activeGroup);
return TPromise.as(void 0);
}
}
\ No newline at end of file
......@@ -40,6 +40,10 @@ import { NextNoTabsTitleControl } from './nextNoTabsTitleControl';
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
import { join } from 'vs/base/common/paths';
import { Direction } from 'vs/platform/editor/common/editor';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { RemoveActiveEditorGroupAction } from 'vs/workbench/browser/parts/editor/editorActions';
import { ActionRunner, IAction } from 'vs/base/common/actions';
export class NextEditorGroupView extends Themable implements INextEditorGroupView {
......@@ -112,7 +116,8 @@ export class NextEditorGroupView extends Themable implements INextEditorGroupVie
@IPartService private partService: IPartService,
@INotificationService private notificationService: INotificationService,
@ITelemetryService private telemetryService: ITelemetryService,
@IUntitledEditorService private untitledEditorService: IUntitledEditorService
@IUntitledEditorService private untitledEditorService: IUntitledEditorService,
@IKeybindingService private keybindingService: IKeybindingService
) {
super(themeService);
......@@ -148,6 +153,9 @@ export class NextEditorGroupView extends Themable implements INextEditorGroupVie
}
}));
// Container toolbar
this.createContainerToolbar();
// Progress bar
this.progressBar = this._register(new ProgressBar(this.element));
this._register(attachProgressBarStyler(this.progressBar, this.themeService));
......@@ -186,6 +194,29 @@ export class NextEditorGroupView extends Themable implements INextEditorGroupVie
this.updateStyles();
}
private createContainerToolbar(): void {
// Toolbar Container
const toolbarContainer = document.createElement('div');
addClass(toolbarContainer, 'editor-group-container-toolbar');
this.element.appendChild(toolbarContainer);
// Toolbar
const groupId = this._group.id;
const containerToolbar = new ActionBar(toolbarContainer, {
ariaLabel: localize('araLabelGroupActions', "Editor group actions"), actionRunner: new class extends ActionRunner {
run(action: IAction) {
return action.run(groupId);
}
}
});
// Toolbar actions
const removeGroupAction = this._register(this.instantiationService.createInstance(RemoveActiveEditorGroupAction, RemoveActiveEditorGroupAction.ID, localize('removeGroupAction', "Collapse Editor Group")));
const keybinding = this.keybindingService.lookupKeybinding(removeGroupAction.id);
containerToolbar.push(removeGroupAction, { icon: true, label: false, keybinding: keybinding ? keybinding.getLabel() : void 0 });
}
private doTrackFocus(): void {
// Container
......
......@@ -18,6 +18,7 @@ import { Registry } from 'vs/platform/registry/common/platform';
import { ITextModel } from 'vs/editor/common/model';
import { Schemas } from 'vs/base/common/network';
import { LRUCache } from 'vs/base/common/map';
import { INextEditorGroupsService, INextEditorGroup } from 'vs/workbench/services/group/common/nextEditorGroupsService';
export const EditorsVisibleContext = new RawContextKey<boolean>('editorIsOpen', false);
export const NoEditorsVisibleContext: ContextKeyExpr = EditorsVisibleContext.toNegated();
......@@ -799,6 +800,15 @@ export interface IEditorIdentifier {
editor: IEditorInput;
}
export function groupFromContext(context: GroupIdentifier, editorGroupService: INextEditorGroupsService): INextEditorGroup {
let group: INextEditorGroup;
if (typeof context === 'number') {
group = editorGroupService.getGroup(context);
}
return group || editorGroupService.activeGroup;
}
/**
* The editor commands context is used for editor commands (e.g. in the editor title)
* and we must ensure that the context is serializable because it potentially travels
......
......@@ -190,8 +190,8 @@ export class Workbench extends Disposable implements IPartService {
private workbenchCreated: boolean;
private workbenchShutdown: boolean;
private nextEditorService: INextEditorService;
private nextEditorGroupsService: INextEditorGroupsService;
private editorService: INextEditorService;
private editorGroupsService: INextEditorGroupsService;
private viewletService: IViewletService;
private contextKeyService: IContextKeyService;
private keybindingService: IKeybindingService;
......@@ -382,10 +382,10 @@ export class Workbench extends Disposable implements IPartService {
const restorePreviousEditorState = !this.hasInitialFilesToOpen;
this.editorPart = this.instantiationService.createInstance(NextEditorPart, Identifiers.EDITOR_PART, restorePreviousEditorState);
this._register(toDisposable(() => this.editorPart.shutdown()));
this.nextEditorGroupsService = this.editorPart;
this.editorGroupsService = this.editorPart;
serviceCollection.set(INextEditorGroupsService, this.editorPart);
this.nextEditorService = this.instantiationService.createInstance(NextEditorService);
serviceCollection.set(INextEditorService, this.nextEditorService);
this.editorService = this.instantiationService.createInstance(NextEditorService);
serviceCollection.set(INextEditorService, this.editorService);
// TODO@grid Remove Legacy Editor Services
const noOpEditorPart = new NoOpEditorPart(this.instantiationService);
......@@ -466,14 +466,14 @@ export class Workbench extends Disposable implements IPartService {
private registerListeners(): void {
// Listen to visible editor changes
this._register(this.nextEditorService.onDidVisibleEditorsChange(() => this.onDidVisibleEditorsChange()));
this._register(this.editorService.onDidVisibleEditorsChange(() => this.onDidVisibleEditorsChange()));
// Listen to editor closing (if we run with --wait)
const filesToWait = this.workbenchParams.configuration.filesToWait;
if (filesToWait) {
const resourcesToWaitFor = filesToWait.paths.map(p => URI.file(p.filePath));
const waitMarkerFile = URI.file(filesToWait.waitMarkerFilePath);
const listenerDispose = this.nextEditorService.onDidCloseEditor(() => this.onEditorClosed(listenerDispose, resourcesToWaitFor, waitMarkerFile));
const listenerDispose = this.editorService.onDidCloseEditor(() => this.onEditorClosed(listenerDispose, resourcesToWaitFor, waitMarkerFile));
this._register(listenerDispose);
}
......@@ -514,14 +514,14 @@ export class Workbench extends Disposable implements IPartService {
// In wait mode, listen to changes to the editors and wait until the files
// are closed that the user wants to wait for. When this happens we delete
// the wait marker file to signal to the outside that editing is done.
if (resourcesToWaitFor.every(resource => !this.nextEditorService.isOpen({ resource }))) {
if (resourcesToWaitFor.every(resource => !this.editorService.isOpen({ resource }))) {
listenerDispose.dispose();
this.fileService.del(waitMarkerFile).done(null, errors.onUnexpectedError);
}
}
private onDidVisibleEditorsChange(): void {
const visibleEditors = this.nextEditorService.visibleControls;
const visibleEditors = this.editorService.visibleControls;
// Close when empty: check if we should close the window based on the setting
// Overruled by: window has a workspace opened or this window is for extension development
......@@ -535,7 +535,7 @@ export class Workbench extends Disposable implements IPartService {
}
private onAllEditorsClosed(): void {
const visibleEditors = this.nextEditorService.visibleControls.length;
const visibleEditors = this.editorService.visibleControls.length;
if (visibleEditors === 0) {
this.windowService.closeWindow();
}
......@@ -582,7 +582,7 @@ export class Workbench extends Disposable implements IPartService {
const multipleEditorGroups = MultipleEditorGroupsContext.bindTo(this.contextKeyService);
const updateEditorContextKeys = () => {
const visibleEditors = this.nextEditorService.visibleControls;
const visibleEditors = this.editorService.visibleControls;
textCompareEditorVisible.set(visibleEditors.some(control => control.getId() === TEXT_DIFF_EDITOR_ID));
......@@ -592,23 +592,23 @@ export class Workbench extends Disposable implements IPartService {
editorsVisibleContext.reset();
}
if (!this.nextEditorService.activeEditor) {
if (!this.editorService.activeEditor) {
activeEditorGroupEmpty.set(true);
} else {
activeEditorGroupEmpty.reset();
}
if (this.nextEditorGroupsService.count > 1) {
if (this.editorGroupsService.count > 1) {
multipleEditorGroups.set(true);
} else {
multipleEditorGroups.reset();
}
};
this._register(this.nextEditorService.onDidActiveEditorChange(() => updateEditorContextKeys()));
this._register(this.nextEditorService.onDidVisibleEditorsChange(() => updateEditorContextKeys()));
this._register(this.nextEditorGroupsService.onDidAddGroup(() => updateEditorContextKeys()));
this._register(this.nextEditorGroupsService.onDidRemoveGroup(() => updateEditorContextKeys()));
this._register(this.editorService.onDidActiveEditorChange(() => updateEditorContextKeys()));
this._register(this.editorService.onDidVisibleEditorsChange(() => updateEditorContextKeys()));
this._register(this.editorGroupsService.onDidAddGroup(() => updateEditorContextKeys()));
this._register(this.editorGroupsService.onDidRemoveGroup(() => updateEditorContextKeys()));
const inputFocused = InputFocusedContext.bindTo(this.contextKeyService);
this._register(DOM.addDisposableListener(window, 'focusin', () => {
......@@ -636,7 +636,7 @@ export class Workbench extends Disposable implements IPartService {
restorePromises.push(this.editorPart.whenRestored.then(() => {
return this.resolveEditorsToOpen().then(inputs => {
if (inputs.length) {
return this.nextEditorService.openEditors(inputs);
return this.editorService.openEditors(inputs);
}
return TPromise.as(void 0);
......@@ -692,7 +692,7 @@ export class Workbench extends Disposable implements IPartService {
customKeybindingsCount: this.keybindingService.customKeybindingsCount(),
pinnedViewlets: this.activitybarPart.getPinned(),
restoredViewlet: viewletIdToRestore,
restoredEditorsCount: this.nextEditorService.visibleEditors.length
restoredEditorsCount: this.editorService.visibleEditors.length
};
};
......@@ -737,7 +737,7 @@ export class Workbench extends Disposable implements IPartService {
// Empty workbench
else if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY && this.openUntitledFile()) {
const isEmpty = this.nextEditorGroupsService.count === 1 && this.nextEditorGroupsService.activeGroup.count === 0;
const isEmpty = this.editorGroupsService.count === 1 && this.editorGroupsService.activeGroup.count === 0;
if (!isEmpty) {
return TPromise.as([]); // do not open any empty untitled file if we restored editors from previous session
}
......@@ -1210,7 +1210,7 @@ export class Workbench extends Disposable implements IPartService {
// Status bar and activity bar visibility come from settings -> update their visibility.
this.onDidUpdateConfiguration(true);
const activeEditor = this.nextEditorService.activeControl;
const activeEditor = this.editorService.activeControl;
if (activeEditor) {
activeEditor.focus();
}
......@@ -1248,19 +1248,19 @@ export class Workbench extends Disposable implements IPartService {
// Enter Centered Editor Layout
if (active) {
if (this.nextEditorGroupsService.count === 1) {
const activeGroup = this.nextEditorGroupsService.activeGroup;
this.nextEditorGroupsService.addGroup(activeGroup, GroupDirection.LEFT);
this.nextEditorGroupsService.addGroup(activeGroup, GroupDirection.RIGHT);
if (this.editorGroupsService.count === 1) {
const activeGroup = this.editorGroupsService.activeGroup;
this.editorGroupsService.addGroup(activeGroup, GroupDirection.LEFT);
this.editorGroupsService.addGroup(activeGroup, GroupDirection.RIGHT);
}
}
// Leave Centered Editor Layout
else {
if (this.nextEditorGroupsService.count === 3) {
this.nextEditorGroupsService.groups.forEach(group => {
if (this.editorGroupsService.count === 3) {
this.editorGroupsService.groups.forEach(group => {
if (group.count === 0) {
this.nextEditorGroupsService.removeGroup(group);
this.editorGroupsService.removeGroup(group);
}
});
}
......@@ -1307,7 +1307,7 @@ export class Workbench extends Disposable implements IPartService {
let promise = TPromise.wrap<any>(null);
if (hidden && this.sidebarPart.getActiveViewlet()) {
promise = this.sidebarPart.hideActiveViewlet().then(() => {
const activeEditor = this.nextEditorService.activeControl;
const activeEditor = this.editorService.activeControl;
const activePanel = this.panelPart.getActivePanel();
// Pass Focus to Editor or Panel if Sidebar is now hidden
......@@ -1360,7 +1360,7 @@ export class Workbench extends Disposable implements IPartService {
promise = this.panelPart.hideActivePanel().then(() => {
// Pass Focus to Editor if Panel part is now hidden
const editor = this.nextEditorService.activeControl;
const editor = this.editorService.activeControl;
if (editor) {
editor.focus();
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册