提交 7c1d60cb 编写于 作者: B Benjamin Pasero

grid - add a way to get a label for a group

上级 3133cbcb
......@@ -26,7 +26,7 @@ import { ITextResourceConfigurationService } from 'vs/editor/common/services/res
import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService';
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
import { isDiffEditor, isCodeEditor } from 'vs/editor/browser/editorBrowser';
import { INextEditorGroupsService } from 'vs/workbench/services/group/common/nextEditorGroupsService';
import { INextEditorGroupsService, INextEditorGroup } from 'vs/workbench/services/group/common/nextEditorGroupsService';
import { CancellationToken } from 'vs/base/common/cancellation';
const TEXT_EDITOR_VIEW_STATE_PREFERENCE_KEY = 'textEditorViewState';
......@@ -56,13 +56,14 @@ export abstract class BaseTextEditor extends BaseEditor {
@IThemeService protected themeService: IThemeService,
@ITextFileService private readonly _textFileService: ITextFileService,
@IEditorGroupService protected editorGroupService: IEditorGroupService,
@INextEditorGroupsService nextEditorGroupService: INextEditorGroupsService
@INextEditorGroupsService private nextEditorGroupService: INextEditorGroupsService
) {
super(id, telemetryService, themeService);
this.editorViewStateMemento = new EditorViewStateMemento<IEditorViewState>(nextEditorGroupService, this.getMemento(storageService, Scope.WORKSPACE), TEXT_EDITOR_VIEW_STATE_PREFERENCE_KEY, 100);
this.toUnbind.push(this.configurationService.onDidChangeConfiguration(e => this.handleConfigurationChangeEvent(this.configurationService.getValue<IEditorConfiguration>(this.getResource()))));
this.toUnbind.push(this.nextEditorGroupService.onDidGroupLabelChange(group => this.handleGroupLabelChange(group)));
}
protected get instantiationService(): IInstantiationService {
......@@ -77,6 +78,12 @@ export abstract class BaseTextEditor extends BaseEditor {
return this._textFileService;
}
private handleGroupLabelChange(group: INextEditorGroup): void {
if (group.id === this.group && this.isVisible() && this.editorControl) {
this.editorControl.updateOptions({ ariaLabel: this.computeAriaLabel() }); // Make sure to update ARIA label if group label of this editor changed
}
}
private handleConfigurationChangeEvent(configuration?: IEditorConfiguration): void {
if (this.isVisible()) {
this.updateEditorConfiguration(configuration);
......@@ -108,8 +115,11 @@ export abstract class BaseTextEditor extends BaseEditor {
let ariaLabel = this.getAriaLabel();
// Apply group information to help identify in which group we are
if (ariaLabel && typeof this.group === 'number') {
ariaLabel = nls.localize('editorLabelWithGroup', "{0}, Group {1}.", ariaLabel, this.group + 1); // TODO@grid do not use group ID in ARIA labels
if (ariaLabel) {
const groupLabel = this.nextEditorGroupService.getLabel(this.group);
if (groupLabel) {
ariaLabel = nls.localize('editorLabelWithGroup', "{0}, {1}.", ariaLabel, groupLabel);
}
}
return ariaLabel;
......
......@@ -33,8 +33,11 @@ import { INotificationService, Severity } from 'vs/platform/notification/common/
import { IWindowService } from 'vs/platform/windows/common/windows';
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { NextEditorDropTarget } from 'vs/workbench/browser/parts/editor2/nextEditorDropTarget';
import { localize } from 'vs/nls';
// TODO@grid enable minimized/maximized groups in one dimension
// - doCreateGroupView(): needs listener if the view gets minimized, the previous active group should become active
// - doSetGroupActive(): needs a listener if the group is minimized, it should now restore to be maximized
interface INextEditorPartUIState {
serializedGrid: ISerializedGrid;
......@@ -65,6 +68,9 @@ export class NextEditorPart extends Part implements INextEditorGroupsService, IN
private _onDidMoveGroup: Emitter<INextEditorGroupView> = this._register(new Emitter<INextEditorGroupView>());
get onDidMoveGroup(): Event<INextEditorGroupView> { return this._onDidMoveGroup.event; }
private _onDidGroupLabelChange: Emitter<INextEditorGroupView> = this._register(new Emitter<INextEditorGroupView>());
get onDidGroupLabelChange(): Event<INextEditorGroupView> { return this._onDidGroupLabelChange.event; }
//#endregion
private memento: object;
......@@ -74,6 +80,7 @@ export class NextEditorPart extends Part implements INextEditorGroupsService, IN
private _activeGroup: INextEditorGroupView;
private groupViews: Map<GroupIdentifier, INextEditorGroupView> = new Map<GroupIdentifier, INextEditorGroupView>();
private mostRecentActiveGroups: GroupIdentifier[] = [];
private mapGroupViewToLabel: Map<GroupIdentifier, string> = new Map<GroupIdentifier, string>();
private container: HTMLElement;
private gridWidget: SerializableGrid<INextEditorGroupView>;
......@@ -165,6 +172,10 @@ export class NextEditorPart extends Part implements INextEditorGroupsService, IN
}
get orientation(): GroupOrientation {
if (!this.gridWidget) {
return void 0; // we have not been created yet
}
return this.gridWidget.orientation === Orientation.VERTICAL ? GroupOrientation.VERTICAL : GroupOrientation.HORIZONTAL;
}
......@@ -179,7 +190,9 @@ export class NextEditorPart extends Part implements INextEditorGroupsService, IN
case GroupsOrder.GRID_ORDER:
const views: INextEditorGroupView[] = [];
this.fillGridNodes(views, this.gridWidget.getViews());
if (this.gridWidget) {
this.fillGridNodes(views, this.gridWidget.getViews());
}
return views;
......@@ -200,6 +213,25 @@ export class NextEditorPart extends Part implements INextEditorGroupsService, IN
return this.groupViews.get(identifier);
}
getLabel(identifier: GroupIdentifier): string {
return this.mapGroupViewToLabel.get(identifier);
}
private updateLabels(): void {
// Assign labels by iterating over groups in grid order and using the index
this.getGroups(GroupsOrder.GRID_ORDER).forEach((group, index) => {
const currentLabel = this.mapGroupViewToLabel.get(group.id);
const newLabel = localize('groupLabel', "Group {0}", index + 1);
this.mapGroupViewToLabel.set(group.id, newLabel);
if (newLabel !== currentLabel) {
this._onDidGroupLabelChange.fire(group);
}
});
}
activateGroup(group: INextEditorGroupView | GroupIdentifier): INextEditorGroupView {
const groupView = this.assertGroupView(group);
this.doSetGroupActive(groupView);
......@@ -231,6 +263,10 @@ export class NextEditorPart extends Part implements INextEditorGroupsService, IN
return; // require at least 2 groups to show
}
if (!this.gridWidget) {
return; // we have not been created yet
}
// Even all group sizes
if (arrangement === GroupsArrangement.EVEN) {
this.groups.forEach(group => {
......@@ -256,6 +292,10 @@ export class NextEditorPart extends Part implements INextEditorGroupsService, IN
}
setGroupOrientation(orientation: GroupOrientation): void {
if (!this.gridWidget) {
return; // we have not been created yet
}
this.gridWidget.orientation = (orientation === GroupOrientation.HORIZONTAL) ? Orientation.HORIZONTAL : Orientation.VERTICAL;
}
......@@ -282,6 +322,9 @@ export class NextEditorPart extends Part implements INextEditorGroupsService, IN
this.toGridViewDirection(direction),
);
// Update labels
this.updateLabels();
// Update container
this.updateContainer();
......@@ -324,8 +367,6 @@ export class NextEditorPart extends Part implements INextEditorGroupsService, IN
// Event
this._onDidAddGroup.fire(groupView);
// TODO@grid if the view gets minimized, the previous active group should become active
return groupView;
}
......@@ -350,8 +391,6 @@ export class NextEditorPart extends Part implements INextEditorGroupsService, IN
// Event
this._onDidActiveGroupChange.fire(group);
// TODO@grid if the group is minimized, it should now restore to be maximized
}
private doUpdateMostRecentActive(group: INextEditorGroupView, makeMostRecentlyActive?: boolean): void {
......@@ -427,6 +466,9 @@ export class NextEditorPart extends Part implements INextEditorGroupsService, IN
this.focusGroup(this._activeGroup);
}
// Update labels
this.updateLabels();
// Update container
this.updateContainer();
......@@ -461,6 +503,9 @@ export class NextEditorPart extends Part implements INextEditorGroupsService, IN
this.focusGroup(targetView);
}
// Update labels
this.updateLabels();
// Event
this._onDidMoveGroup.fire(groupView);
......@@ -585,6 +630,9 @@ export class NextEditorPart extends Part implements INextEditorGroupsService, IN
// Signal restored
always(TPromise.join(this.groups.map(group => group.whenRestored)), () => this.whenRestoredComplete(void 0));
// Update labels
this.updateLabels();
// Update container
this.updateContainer();
}
......@@ -768,16 +816,18 @@ export class NextEditorPart extends Part implements INextEditorGroupsService, IN
shutdown(): void {
// Persist grid UI state
const uiState: INextEditorPartUIState = {
serializedGrid: this.gridWidget.serialize(),
activeGroup: this._activeGroup.id,
mostRecentActiveGroups: this.mostRecentActiveGroups
};
if (this.isEmpty()) {
delete this.memento[NextEditorPart.NEXT_EDITOR_PART_UI_STATE_STORAGE_KEY];
} else {
this.memento[NextEditorPart.NEXT_EDITOR_PART_UI_STATE_STORAGE_KEY] = uiState;
if (this.gridWidget) {
const uiState: INextEditorPartUIState = {
serializedGrid: this.gridWidget.serialize(),
activeGroup: this._activeGroup.id,
mostRecentActiveGroups: this.mostRecentActiveGroups
};
if (this.isEmpty()) {
delete this.memento[NextEditorPart.NEXT_EDITOR_PART_UI_STATE_STORAGE_KEY];
} else {
this.memento[NextEditorPart.NEXT_EDITOR_PART_UI_STATE_STORAGE_KEY] = uiState;
}
}
// Forward to all groups
......
......@@ -103,6 +103,11 @@ export interface INextEditorGroupsService {
*/
readonly onDidMoveGroup: Event<INextEditorGroup>;
/**
* An event for when the label of a group changes.
*/
readonly onDidGroupLabelChange: Event<INextEditorGroup>;
/**
* An active group is the default location for new editors to open.
*/
......@@ -134,6 +139,11 @@ export interface INextEditorGroupsService {
*/
getGroup(identifier: GroupIdentifier): INextEditorGroup;
/**
* A human readable label for a group.
*/
getLabel(identifier: GroupIdentifier): string;
/**
* Move keyboard focus into the provided group.
*/
......
......@@ -114,12 +114,19 @@ suite('Next editor2 part tests', () => {
groupMovedCounter++;
});
let groupLabelChangeCounter = 0;
const groupLabelChangeListener = part.onDidGroupLabelChange(() => {
groupLabelChangeCounter++;
});
// always a root group
const rootGroup = part.groups[0];
assert.equal(part.groups.length, 1);
assert.equal(part.count, 1);
assert.equal(rootGroup, part.getGroup(rootGroup.id));
assert.ok(part.activeGroup === rootGroup);
assert.equal(groupLabelChangeCounter, 0);
assert.equal(part.getLabel(rootGroup.id), 'Group 1');
let mru = part.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE);
assert.equal(mru.length, 1);
......@@ -131,6 +138,9 @@ suite('Next editor2 part tests', () => {
assert.equal(part.groups.length, 2);
assert.equal(part.count, 2);
assert.ok(part.activeGroup === rootGroup);
assert.equal(groupLabelChangeCounter, 1);
assert.equal(part.getLabel(rootGroup.id), 'Group 1');
assert.equal(part.getLabel(rightGroup.id), 'Group 2');
mru = part.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE);
assert.equal(mru.length, 2);
......@@ -157,6 +167,10 @@ suite('Next editor2 part tests', () => {
assert.equal(part.groups.length, 3);
assert.ok(part.activeGroup === rightGroup);
assert.ok(!downGroup.activeControl);
assert.equal(groupLabelChangeCounter, 2);
assert.equal(part.getLabel(rootGroup.id), 'Group 1');
assert.equal(part.getLabel(rightGroup.id), 'Group 2');
assert.equal(part.getLabel(downGroup.id), 'Group 3');
mru = part.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE);
assert.equal(mru.length, 3);
......@@ -217,6 +231,7 @@ suite('Next editor2 part tests', () => {
groupAddedListener.dispose();
groupRemovedListener.dispose();
groupMovedListener.dispose();
groupLabelChangeListener.dispose();
part.dispose();
});
......
......@@ -706,6 +706,7 @@ export class TestNextEditorGroupsService implements INextEditorGroupsService {
onDidAddGroup: Event<INextEditorGroup> = Event.None;
onDidRemoveGroup: Event<INextEditorGroup> = Event.None;
onDidMoveGroup: Event<INextEditorGroup> = Event.None;
onDidGroupLabelChange: Event<INextEditorGroup> = Event.None;
orientation: any;
......@@ -731,6 +732,10 @@ export class TestNextEditorGroupsService implements INextEditorGroupsService {
return void 0;
}
getLabel(identifier: number): string {
return 'Group 1';
}
focusGroup(group: number | INextEditorGroup): INextEditorGroup {
return null;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册