statusbar - use model as only truth for sort order

This commit is contained in:
Benjamin Pasero
2021-09-13 12:17:45 +02:00
parent c16cd29d10
commit 4eae83a523
4 changed files with 22 additions and 65 deletions
@@ -3,7 +3,6 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/statusbarpart';
import { localize } from 'vs/nls';
import { IStatusbarService } from 'vs/workbench/services/statusbar/browser/statusbar';
import { Action } from 'vs/base/common/actions';
@@ -17,6 +16,8 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
import { StatusbarViewModel } from 'vs/workbench/browser/parts/statusbar/statusbarModel';
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
export const CONTEXT_STATUS_BAR_FOCUSED = new RawContextKey<boolean>('statusBarFocused', false, localize('statusBarFocused', "Whether the status bar has keyboard focus"));
export class ToggleStatusbarEntryVisibilityAction extends Action {
constructor(id: string, label: string, private model: StatusbarViewModel) {
@@ -45,8 +46,6 @@ export class HideStatusbarEntryAction extends Action {
}
}
export const CONTEXT_STATUS_BAR_FOCUSED = new RawContextKey<boolean>('statusBarFocused', false, localize('statusBarFocused', "Whether the status bar has keyboard focus"));
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'workbench.statusBar.focusPrevious',
weight: KeybindingWeight.WorkbenchContrib,
@@ -3,7 +3,6 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/statusbarpart';
import { toErrorMessage } from 'vs/base/common/errorMessage';
import { Disposable, MutableDisposable } from 'vs/base/common/lifecycle';
import { SimpleIconLabel } from 'vs/base/browser/ui/iconLabel/simpleIconLabel';
@@ -9,7 +9,7 @@ import { hide, show, isAncestor } from 'vs/base/browser/dom';
import { IStorageService, StorageScope, IStorageValueChangeEvent, StorageTarget } from 'vs/platform/storage/common/storage';
import { Emitter } from 'vs/base/common/event';
interface IStatusbarEntryPriority {
export interface IStatusbarEntryPriority {
/**
* The main priority of the entry that
@@ -40,7 +40,7 @@ export interface IStatusbarViewModelEntry {
export class StatusbarViewModel extends Disposable {
static readonly HIDDEN_ENTRIES_KEY = 'workbench.statusbar.hidden';
private static readonly HIDDEN_ENTRIES_KEY = 'workbench.statusbar.hidden';
private readonly _onDidChangeEntryVisibility = this._register(new Emitter<{ id: string, visible: boolean }>());
readonly onDidChangeEntryVisibility = this._onDidChangeEntryVisibility.event;
@@ -186,9 +186,11 @@ export class StatusbarViewModel extends Disposable {
}
isEntryFocused(): boolean {
const focused = this._entries.find(entry => isAncestor(document.activeElement, entry.container));
return !!this.getFocusedEntry();
}
return !!focused;
private getFocusedEntry(): IStatusbarViewModelEntry | undefined {
return this._entries.find(entry => isAncestor(document.activeElement, entry.container));
}
private focusEntry(delta: number, restartPosition: number): void {
@@ -204,7 +206,7 @@ export class StatusbarViewModel extends Disposable {
return entry;
};
const focused = this._entries.find(entry => isAncestor(document.activeElement, entry.container));
const focused = this.getFocusedEntry();
if (focused) {
const entry = getVisibleEntry(this._entries.indexOf(focused) + delta);
if (entry) {
@@ -31,29 +31,9 @@ import { IHoverService } from 'vs/workbench/services/hover/browser/hover';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IHoverDelegate, IHoverDelegateOptions } from 'vs/base/browser/ui/iconLabel/iconHoverDelegate';
import { CONTEXT_STATUS_BAR_FOCUSED, HideStatusbarEntryAction, ToggleStatusbarEntryVisibilityAction } from 'vs/workbench/browser/parts/statusbar/statusbarActions';
import { IStatusbarViewModelEntry, StatusbarViewModel } from 'vs/workbench/browser/parts/statusbar/statusbarModel';
import { IStatusbarEntryPriority, IStatusbarViewModelEntry, StatusbarViewModel } from 'vs/workbench/browser/parts/statusbar/statusbarModel';
import { StatusbarEntryItem } from 'vs/workbench/browser/parts/statusbar/statusbarItem';
interface IStatusbarEntryPriority {
/**
* The main priority of the entry that
* defines the order of appearance.
*
* May not be unique across all entries.
*/
readonly primary: number;
/**
* The secondary priority of the entry
* is used in case the main priority
* matches another one's priority.
*
* Should be unique across all entries.
*/
readonly secondary: number;
}
interface IPendingStatusbarEntry {
readonly id: string;
readonly alignment: StatusbarAlignment;
@@ -160,9 +140,6 @@ export class StatusbarPart extends Part implements IStatusbarService {
const itemContainer = this.doCreateStatusItem(id, alignment, ...coalesce([entry.showBeak ? 'has-beak' : undefined]));
const item = this.instantiationService.createInstance(StatusbarEntryItem, itemContainer, entry, this.hoverDelegate);
// Append to parent
this.appendOneStatusbarEntry(itemContainer, alignment, priority);
// Add to view model
const viewModelEntry: IStatusbarViewModelEntry = new class implements IStatusbarViewModelEntry {
readonly id = id;
@@ -175,6 +152,9 @@ export class StatusbarPart extends Part implements IStatusbarService {
};
const viewModelEntryDispose = this.viewModel.add(viewModelEntry);
// Append to parent
this.appendOneStatusbarEntry(viewModelEntry);
return {
update: entry => {
item.update(entry);
@@ -276,43 +256,20 @@ export class StatusbarPart extends Part implements IStatusbarService {
}
}
private appendOneStatusbarEntry(itemContainer: HTMLElement, alignment: StatusbarAlignment, priority: IStatusbarEntryPriority): void {
const entries = this.viewModel.getEntries(alignment);
private appendOneStatusbarEntry(entry: IStatusbarViewModelEntry): void {
const entries = this.viewModel.getEntries(entry.alignment);
if (alignment === StatusbarAlignment.RIGHT) {
if (entry.alignment === StatusbarAlignment.RIGHT) {
entries.reverse(); // reversing due to flex: row-reverse
}
const target = assertIsDefined(alignment === StatusbarAlignment.LEFT ? this.leftItemsContainer : this.rightItemsContainer);
const target = assertIsDefined(entry.alignment === StatusbarAlignment.LEFT ? this.leftItemsContainer : this.rightItemsContainer);
// find an entry that has lower priority than the new one
// and then insert the item before that one
let appended = false;
for (const entry of entries) {
// pick a priority that ideally is not the same
// by falling back to secondary priority
let existingEntryPriority = entry.priority.primary;
let newEntryPriority = priority.primary;
if (existingEntryPriority === newEntryPriority) {
existingEntryPriority = entry.priority.secondary;
newEntryPriority = priority.secondary;
}
// insert according to priority
if (
alignment === StatusbarAlignment.LEFT && existingEntryPriority < newEntryPriority ||
alignment === StatusbarAlignment.RIGHT && existingEntryPriority > newEntryPriority // reversing due to flex: row-reverse
) {
target.insertBefore(itemContainer, entry.container);
appended = true;
break;
}
}
// Fallback to just appending otherwise
if (!appended) {
target.appendChild(itemContainer);
const index = entries.indexOf(entry);
if (index + 1 === entries.length) {
target.appendChild(entry.container); // append at the end if last
} else {
target.insertBefore(entry.container, entries[index + 1].container); // insert before next element otherwise
}
}