mirror of
https://github.com/microsoft/vscode.git
synced 2026-09-21 03:36:14 +01:00
statusbar - allow to show hover on click
//cc @jrieken
This commit is contained in:
@@ -14,7 +14,6 @@ import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { isFunction, isString } from 'vs/base/common/types';
|
||||
import { localize } from 'vs/nls';
|
||||
|
||||
|
||||
export function setupNativeHover(htmlElement: HTMLElement, tooltip: string | IIconLabelMarkdownString | undefined): void {
|
||||
if (isString(tooltip)) {
|
||||
htmlElement.title = tooltip;
|
||||
@@ -25,7 +24,20 @@ export function setupNativeHover(htmlElement: HTMLElement, tooltip: string | IIc
|
||||
}
|
||||
}
|
||||
|
||||
export function setupCustomHover(hoverDelegate: IHoverDelegate, htmlElement: HTMLElement, markdownTooltip: string | IIconLabelMarkdownString | HTMLElement | undefined): IDisposable | undefined {
|
||||
export interface ICustomHover extends IDisposable {
|
||||
|
||||
/**
|
||||
* Allows to programmatically open the hover.
|
||||
*/
|
||||
show(): void;
|
||||
|
||||
/**
|
||||
* Allows to programmatically hide the hover.
|
||||
*/
|
||||
hide(): void;
|
||||
}
|
||||
|
||||
export function setupCustomHover(hoverDelegate: IHoverDelegate, htmlElement: HTMLElement, markdownTooltip: string | IIconLabelMarkdownString | HTMLElement | undefined): ICustomHover | undefined {
|
||||
if (!markdownTooltip) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -36,7 +48,18 @@ export function setupCustomHover(hoverDelegate: IHoverDelegate, htmlElement: HTM
|
||||
|
||||
let hoverWidget: IDisposable | undefined;
|
||||
|
||||
const mouseEnter = (e: MouseEvent) => {
|
||||
const hideHover = (disposeWidget: boolean, disposePreparation: boolean) => {
|
||||
if (disposeWidget) {
|
||||
hoverWidget?.dispose();
|
||||
hoverWidget = undefined;
|
||||
}
|
||||
if (disposePreparation) {
|
||||
hoverPreparation?.dispose();
|
||||
hoverPreparation = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
const showHoverDelayed = (delay: number) => {
|
||||
if (hoverPreparation) {
|
||||
return;
|
||||
}
|
||||
@@ -45,14 +68,7 @@ export function setupCustomHover(hoverDelegate: IHoverDelegate, htmlElement: HTM
|
||||
|
||||
const mouseLeaveOrDown = (e: MouseEvent) => {
|
||||
const isMouseDown = e.type === dom.EventType.MOUSE_DOWN;
|
||||
if (isMouseDown) {
|
||||
hoverWidget?.dispose();
|
||||
hoverWidget = undefined;
|
||||
}
|
||||
if (isMouseDown || (<any>e).fromElement === htmlElement) {
|
||||
hoverPreparation?.dispose();
|
||||
hoverPreparation = undefined;
|
||||
}
|
||||
hideHover(isMouseDown, isMouseDown || (<any>e).fromElement === htmlElement);
|
||||
};
|
||||
const mouseLeaveDomListener = dom.addDisposableListener(htmlElement, dom.EventType.MOUSE_LEAVE, mouseLeaveOrDown, true);
|
||||
const mouseDownDownListener = dom.addDisposableListener(htmlElement, dom.EventType.MOUSE_DOWN, mouseLeaveOrDown, true);
|
||||
@@ -99,7 +115,7 @@ export function setupCustomHover(hoverDelegate: IHoverDelegate, htmlElement: HTM
|
||||
}
|
||||
mouseMoveDomListener?.dispose();
|
||||
};
|
||||
const timeout = new RunOnceScheduler(showHover, hoverDelegate.delay);
|
||||
const timeout = new RunOnceScheduler(showHover, delay);
|
||||
timeout.schedule();
|
||||
|
||||
hoverPreparation = toDisposable(() => {
|
||||
@@ -110,15 +126,21 @@ export function setupCustomHover(hoverDelegate: IHoverDelegate, htmlElement: HTM
|
||||
tokenSource.dispose(true);
|
||||
});
|
||||
};
|
||||
const mouseOverDomEmitter = dom.addDisposableListener(htmlElement, dom.EventType.MOUSE_OVER, mouseEnter, true);
|
||||
return toDisposable(() => {
|
||||
mouseOverDomEmitter.dispose();
|
||||
hoverPreparation?.dispose();
|
||||
hoverWidget?.dispose();
|
||||
});
|
||||
const mouseOverDomEmitter = dom.addDisposableListener(htmlElement, dom.EventType.MOUSE_OVER, () => showHoverDelayed(hoverDelegate.delay), true);
|
||||
return {
|
||||
show: () => {
|
||||
showHoverDelayed(0); // show hover immediately
|
||||
},
|
||||
hide: () => {
|
||||
hideHover(true, true);
|
||||
},
|
||||
dispose: () => {
|
||||
mouseOverDomEmitter.dispose();
|
||||
hideHover(true, true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function getTooltipForCustom(markdownTooltip: string | IIconLabelMarkdownString | HTMLElement): (token: CancellationToken) => Promise<string | IMarkdownString | HTMLElement | undefined> {
|
||||
if (isString(markdownTooltip) || markdownTooltip instanceof HTMLElement) {
|
||||
return async () => markdownTooltip;
|
||||
|
||||
@@ -13,7 +13,7 @@ import { Part } from 'vs/workbench/browser/part';
|
||||
import { EventType as TouchEventType, Gesture, GestureEvent } from 'vs/base/browser/touch';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { StatusbarAlignment, IStatusbarService, IStatusbarEntry, IStatusbarEntryAccessor } from 'vs/workbench/services/statusbar/browser/statusbar';
|
||||
import { StatusbarAlignment, IStatusbarService, IStatusbarEntry, IStatusbarEntryAccessor, ShowTooltipCommand } from 'vs/workbench/services/statusbar/browser/statusbar';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { Action, IAction, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification, Separator, toAction } from 'vs/base/common/actions';
|
||||
import { IThemeService, registerThemingParticipant, ThemeColor } from 'vs/platform/theme/common/themeService';
|
||||
@@ -44,7 +44,7 @@ import { Action2, registerAction2 } from 'vs/platform/actions/common/actions';
|
||||
import { CATEGORIES } from 'vs/workbench/common/actions';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { hash } from 'vs/base/common/hash';
|
||||
import { setupCustomHover } from 'vs/base/browser/ui/iconLabel/iconLabelHover';
|
||||
import { ICustomHover, setupCustomHover } from 'vs/base/browser/ui/iconLabel/iconLabelHover';
|
||||
import { IHoverService } from 'vs/workbench/services/hover/browser/hover';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { isMarkdownString, markdownStringEqual } from 'vs/base/common/htmlContent';
|
||||
@@ -58,7 +58,7 @@ interface IStatusbarEntryPriority {
|
||||
*
|
||||
* May not be unique across all entries.
|
||||
*/
|
||||
primary: number;
|
||||
readonly primary: number;
|
||||
|
||||
/**
|
||||
* The secondary priority of the entry
|
||||
@@ -67,24 +67,25 @@ interface IStatusbarEntryPriority {
|
||||
*
|
||||
* Should be unique across all entries.
|
||||
*/
|
||||
secondary: number;
|
||||
readonly secondary: number;
|
||||
}
|
||||
|
||||
interface IPendingStatusbarEntry {
|
||||
id: string;
|
||||
readonly id: string;
|
||||
readonly alignment: StatusbarAlignment;
|
||||
readonly priority: IStatusbarEntryPriority;
|
||||
|
||||
entry: IStatusbarEntry;
|
||||
alignment: StatusbarAlignment;
|
||||
priority: IStatusbarEntryPriority;
|
||||
accessor?: IStatusbarEntryAccessor;
|
||||
}
|
||||
|
||||
interface IStatusbarViewModelEntry {
|
||||
id: string;
|
||||
name: string;
|
||||
alignment: StatusbarAlignment;
|
||||
priority: IStatusbarEntryPriority;
|
||||
container: HTMLElement;
|
||||
labelContainer: HTMLElement;
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
readonly alignment: StatusbarAlignment;
|
||||
readonly priority: IStatusbarEntryPriority;
|
||||
readonly container: HTMLElement;
|
||||
readonly labelContainer: HTMLElement;
|
||||
}
|
||||
|
||||
const CONTEXT_STATUS_BAR_FOCUSED = new RawContextKey<boolean>('statusBarFocused', false, localize('statusBarFocused', "Whether the status bar has keyboard focus"));
|
||||
@@ -104,7 +105,7 @@ class StatusbarViewModel extends Disposable {
|
||||
return this._lastFocusedEntry && !this.isHidden(this._lastFocusedEntry.id) ? this._lastFocusedEntry : undefined;
|
||||
}
|
||||
|
||||
private hidden!: Set<string>;
|
||||
private hidden = new Set<string>();
|
||||
|
||||
constructor(private readonly storageService: IStorageService) {
|
||||
super();
|
||||
@@ -123,10 +124,6 @@ class StatusbarViewModel extends Disposable {
|
||||
// ignore parsing errors
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.hidden) {
|
||||
this.hidden = new Set<string>();
|
||||
}
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
@@ -146,34 +143,37 @@ class StatusbarViewModel extends Disposable {
|
||||
const changed = new Set<string>();
|
||||
|
||||
// Check for each entry that is now visible
|
||||
currentlyHidden.forEach(id => {
|
||||
for (const id of currentlyHidden) {
|
||||
if (!this.hidden.has(id)) {
|
||||
changed.add(id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Check for each entry that is now hidden
|
||||
this.hidden.forEach(id => {
|
||||
for (const id of this.hidden) {
|
||||
if (!currentlyHidden.has(id)) {
|
||||
changed.add(id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Update visibility for entries have changed
|
||||
if (changed.size > 0) {
|
||||
this._entries.forEach(entry => {
|
||||
for (const entry of this._entries) {
|
||||
if (changed.has(entry.id)) {
|
||||
this.updateVisibility(entry.id, true);
|
||||
|
||||
changed.delete(entry.id);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
add(entry: IStatusbarViewModelEntry): IDisposable {
|
||||
this._entries.push(entry); // intentionally not using a map here since multiple entries can have the same ID!
|
||||
|
||||
// Intentionally not using a map here since
|
||||
// multiple entries can have the same ID!
|
||||
this._entries.push(entry);
|
||||
|
||||
// Update visibility directly
|
||||
this.updateVisibility(entry, false);
|
||||
@@ -239,10 +239,12 @@ class StatusbarViewModel extends Disposable {
|
||||
|
||||
isEntryFocused(): boolean {
|
||||
const focused = this._entries.find(entry => isAncestor(document.activeElement, entry.container));
|
||||
|
||||
return !!focused;
|
||||
}
|
||||
|
||||
private focusEntry(delta: number, restartPosition: number): void {
|
||||
|
||||
const getVisibleEntry = (start: number) => {
|
||||
let indexToFocus = start;
|
||||
let entry = (indexToFocus >= 0 && indexToFocus < this._entries.length) ? this._entries[indexToFocus] : undefined;
|
||||
@@ -250,6 +252,7 @@ class StatusbarViewModel extends Disposable {
|
||||
indexToFocus += delta;
|
||||
entry = (indexToFocus >= 0 && indexToFocus < this._entries.length) ? this._entries[indexToFocus] : undefined;
|
||||
}
|
||||
|
||||
return entry;
|
||||
};
|
||||
|
||||
@@ -258,7 +261,9 @@ class StatusbarViewModel extends Disposable {
|
||||
const entry = getVisibleEntry(this._entries.indexOf(focused) + delta);
|
||||
if (entry) {
|
||||
this._lastFocusedEntry = entry;
|
||||
|
||||
entry.labelContainer.focus();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -432,7 +437,11 @@ export class StatusbarPart extends Part implements IStatusbarService {
|
||||
private leftItemsContainer: HTMLElement | undefined;
|
||||
private rightItemsContainer: HTMLElement | undefined;
|
||||
|
||||
private hoverDelegate: IHoverDelegate;
|
||||
private readonly hoverDelegate: IHoverDelegate = {
|
||||
showHover: (options: IHoverDelegateOptions) => this.hoverService.showHover(options),
|
||||
delay: this.configurationService.getValue<number>('workbench.hover.delay'),
|
||||
placement: 'element'
|
||||
};
|
||||
|
||||
constructor(
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@@ -442,18 +451,12 @@ export class StatusbarPart extends Part implements IStatusbarService {
|
||||
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
|
||||
@IContextMenuService private contextMenuService: IContextMenuService,
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
@IHoverService hoverService: IHoverService,
|
||||
@IConfigurationService configurationService: IConfigurationService
|
||||
@IHoverService private readonly hoverService: IHoverService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService
|
||||
) {
|
||||
super(Parts.STATUSBAR_PART, { hasTitle: false }, themeService, storageService, layoutService);
|
||||
|
||||
this.registerListeners();
|
||||
|
||||
this.hoverDelegate = {
|
||||
showHover: (options: IHoverDelegateOptions) => hoverService.showHover(options),
|
||||
delay: <number>configurationService.getValue('workbench.hover.delay'),
|
||||
placement: 'element'
|
||||
};
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
@@ -613,14 +616,14 @@ export class StatusbarPart extends Part implements IStatusbarService {
|
||||
private appendAllStatusbarEntries(): void {
|
||||
|
||||
// Append in order of priority
|
||||
[
|
||||
for (const entry of [
|
||||
...this.viewModel.getEntries(StatusbarAlignment.LEFT),
|
||||
...this.viewModel.getEntries(StatusbarAlignment.RIGHT).reverse() // reversing due to flex: row-reverse
|
||||
].forEach(entry => {
|
||||
]) {
|
||||
const target = assertIsDefined(entry.alignment === StatusbarAlignment.LEFT ? this.leftItemsContainer : this.rightItemsContainer);
|
||||
|
||||
target.appendChild(entry.container);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private appendOneStatusbarEntry(itemContainer: HTMLElement, alignment: StatusbarAlignment, priority: IStatusbarEntryPriority): void {
|
||||
@@ -696,12 +699,12 @@ export class StatusbarPart extends Part implements IStatusbarService {
|
||||
// having the same identifier (e.g. from extensions). So we make sure to only
|
||||
// show a single entry per identifier we handled.
|
||||
const handledEntries = new Set<string>();
|
||||
this.viewModel.entries.forEach(entry => {
|
||||
for (const entry of this.viewModel.entries) {
|
||||
if (!handledEntries.has(entry.id)) {
|
||||
actions.push(new ToggleStatusbarEntryVisibilityAction(entry.id, entry.name, this.viewModel));
|
||||
handledEntries.add(entry.id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Figure out if mouse is over an entry
|
||||
let statusEntryUnderMouse: IStatusbarViewModelEntry | undefined = undefined;
|
||||
@@ -839,8 +842,6 @@ class StatusbarEntryItem extends Disposable {
|
||||
readonly labelContainer: HTMLElement;
|
||||
private readonly label: StatusBarCodiconLabel;
|
||||
|
||||
private customHover: IDisposable | undefined;
|
||||
|
||||
private entry: IStatusbarEntry | undefined = undefined;
|
||||
get name(): string { return assertIsDefined(this.entry).name; }
|
||||
|
||||
@@ -850,10 +851,12 @@ class StatusbarEntryItem extends Disposable {
|
||||
private readonly commandMouseListener = this._register(new MutableDisposable());
|
||||
private readonly commandKeyboardListener = this._register(new MutableDisposable());
|
||||
|
||||
private readonly hover = this._register(new MutableDisposable<ICustomHover>());
|
||||
|
||||
constructor(
|
||||
private container: HTMLElement,
|
||||
entry: IStatusbarEntry,
|
||||
private readonly customHoverDelegate: IHoverDelegate,
|
||||
private readonly hoverDelegate: IHoverDelegate,
|
||||
@ICommandService private readonly commandService: ICommandService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
||||
@@ -891,23 +894,23 @@ class StatusbarEntryItem extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
// Update: ARIA label
|
||||
//
|
||||
// Set the aria label on both elements so screen readers would read
|
||||
// the correct thing without duplication #96210
|
||||
|
||||
if (!this.entry || entry.ariaLabel !== this.entry.ariaLabel) {
|
||||
this.container.setAttribute('aria-label', entry.ariaLabel);
|
||||
this.labelContainer.setAttribute('aria-label', entry.ariaLabel);
|
||||
}
|
||||
|
||||
if (!this.entry || entry.role !== this.entry.role) {
|
||||
this.labelContainer.setAttribute('role', entry.role || 'button');
|
||||
}
|
||||
|
||||
// Update: Tooltip (on the container, because label can be disabled)
|
||||
if (!this.entry || !isEqualTooltip(this.entry, entry)) {
|
||||
if (this.customHover) {
|
||||
this.customHover.dispose();
|
||||
this.customHover = undefined;
|
||||
}
|
||||
this.customHover = setupCustomHover(this.customHoverDelegate, this.labelContainer, { markdown: entry.tooltip, markdownNotSupportedFallback: undefined });
|
||||
// Update: Hover (on the container, because label can be disabled)
|
||||
if (!this.entry || !this.isEqualTooltip(this.entry, entry)) {
|
||||
this.hover.value = setupCustomHover(this.hoverDelegate, this.labelContainer, { markdown: entry.tooltip, markdownNotSupportedFallback: undefined });
|
||||
}
|
||||
|
||||
// Update: Command
|
||||
@@ -916,7 +919,7 @@ class StatusbarEntryItem extends Disposable {
|
||||
this.commandKeyboardListener.clear();
|
||||
|
||||
const command = entry.command;
|
||||
if (command) {
|
||||
if (command && (command !== ShowTooltipCommand || this.hover.value) /* "Show Hover" is only valid when we have a hover */) {
|
||||
this.commandMouseListener.value = addDisposableListener(this.labelContainer, EventType.CLICK, () => this.executeCommand(command));
|
||||
this.commandKeyboardListener.value = addDisposableListener(this.labelContainer, EventType.KEY_DOWN, e => {
|
||||
const event = new StandardKeyboardEvent(e);
|
||||
@@ -955,15 +958,36 @@ class StatusbarEntryItem extends Disposable {
|
||||
this.entry = entry;
|
||||
}
|
||||
|
||||
private async executeCommand(command: string | Command): Promise<void> {
|
||||
const id = typeof command === 'string' ? command : command.id;
|
||||
const args = typeof command === 'string' ? [] : command.arguments ?? [];
|
||||
private isEqualTooltip({ tooltip }: IStatusbarEntry, { tooltip: otherTooltip }: IStatusbarEntry) {
|
||||
if (tooltip === undefined) {
|
||||
return otherTooltip === undefined;
|
||||
}
|
||||
|
||||
this.telemetryService.publicLog2<WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification>('workbenchActionExecuted', { id, from: 'status bar' });
|
||||
try {
|
||||
await this.commandService.executeCommand(id, ...args);
|
||||
} catch (error) {
|
||||
this.notificationService.error(toErrorMessage(error));
|
||||
if (isMarkdownString(tooltip)) {
|
||||
return isMarkdownString(otherTooltip) && markdownStringEqual(tooltip, otherTooltip);
|
||||
}
|
||||
|
||||
return tooltip === otherTooltip;
|
||||
}
|
||||
|
||||
private async executeCommand(command: string | Command): Promise<void> {
|
||||
|
||||
// Custom command from us: Show tooltip
|
||||
if (command === ShowTooltipCommand) {
|
||||
this.hover.value?.show();
|
||||
}
|
||||
|
||||
// Any other command is going through command service
|
||||
else {
|
||||
const id = typeof command === 'string' ? command : command.id;
|
||||
const args = typeof command === 'string' ? [] : command.arguments ?? [];
|
||||
|
||||
this.telemetryService.publicLog2<WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification>('workbenchActionExecuted', { id, from: 'status bar' });
|
||||
try {
|
||||
await this.commandService.executeCommand(id, ...args);
|
||||
} catch (error) {
|
||||
this.notificationService.error(toErrorMessage(error));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1006,30 +1030,6 @@ class StatusbarEntryItem extends Disposable {
|
||||
container.style.color = colorResult ?? '';
|
||||
}
|
||||
}
|
||||
|
||||
override dispose(): void {
|
||||
super.dispose();
|
||||
|
||||
dispose(this.foregroundListener);
|
||||
dispose(this.backgroundListener);
|
||||
dispose(this.commandMouseListener);
|
||||
dispose(this.commandKeyboardListener);
|
||||
if (this.customHover) {
|
||||
this.customHover.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isEqualTooltip(e1: IStatusbarEntry, e2: IStatusbarEntry) {
|
||||
const t1 = e1.tooltip;
|
||||
const t2 = e2.tooltip;
|
||||
if (t1 === undefined) {
|
||||
return t2 === undefined;
|
||||
}
|
||||
if (isMarkdownString(t1)) {
|
||||
return isMarkdownString(t2) && markdownStringEqual(t1, t2);
|
||||
}
|
||||
return t1 === t2;
|
||||
}
|
||||
|
||||
registerThemingParticipant((theme, collector) => {
|
||||
|
||||
@@ -17,7 +17,7 @@ import { NOTIFICATIONS_BORDER, STATUS_BAR_ITEM_ACTIVE_BACKGROUND } from 'vs/work
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { ILanguageStatus, ILanguageStatusService } from 'vs/workbench/services/languageStatus/common/languageStatusService';
|
||||
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
|
||||
import { IStatusbarEntry, IStatusbarEntryAccessor, IStatusbarService, StatusbarAlignment } from 'vs/workbench/services/statusbar/browser/statusbar';
|
||||
import { IStatusbarEntry, IStatusbarEntryAccessor, IStatusbarService, ShowTooltipCommand, StatusbarAlignment } from 'vs/workbench/services/statusbar/browser/statusbar';
|
||||
import { parseLinkedText } from 'vs/base/common/linkedText';
|
||||
import { Link } from 'vs/platform/opener/browser/link';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
@@ -174,6 +174,7 @@ class EditorStatusContribution implements IWorkbenchContribution {
|
||||
ariaLabel: localize('langStatus.aria', "Editor Language Status: {0}", ariaLabels.join(', next: ')),
|
||||
tooltip: element,
|
||||
text,
|
||||
command: ShowTooltipCommand
|
||||
};
|
||||
if (!this._combinedEntry) {
|
||||
this._combinedEntry = this._statusBarService.addEntry(props, EditorStatusContribution._id, StatusbarAlignment.RIGHT, 100.11);
|
||||
|
||||
@@ -17,6 +17,11 @@ export const enum StatusbarAlignment {
|
||||
RIGHT
|
||||
}
|
||||
|
||||
export const ShowTooltipCommand: Command = {
|
||||
id: 'statusBar.entry.showTooltip',
|
||||
title: ''
|
||||
};
|
||||
|
||||
/**
|
||||
* A declarative way of describing a status bar entry
|
||||
*/
|
||||
@@ -62,9 +67,12 @@ export interface IStatusbarEntry {
|
||||
readonly backgroundColor?: string | ThemeColor;
|
||||
|
||||
/**
|
||||
* An optional id of a command that is known to the workbench to execute on click
|
||||
* An optional command to execute on click.
|
||||
*
|
||||
* Can use the special `ShowTooltipCommand` to
|
||||
* show the tooltip on click if provided.
|
||||
*/
|
||||
readonly command?: string | Command;
|
||||
readonly command?: string | Command | typeof ShowTooltipCommand;
|
||||
|
||||
/**
|
||||
* Whether to show a beak above the status bar entry.
|
||||
@@ -75,7 +83,6 @@ export interface IStatusbarEntry {
|
||||
* Will enable a spinning icon in front of the text to indicate progress.
|
||||
*/
|
||||
readonly showProgress?: boolean;
|
||||
|
||||
}
|
||||
|
||||
export interface IStatusbarService {
|
||||
|
||||
Reference in New Issue
Block a user