mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-28 12:33:35 +01:00
@@ -4,6 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { HoverPosition } from 'vs/base/browser/ui/hover/hoverWidget';
|
||||
import { IUpdatableHoverOptions } from 'vs/base/browser/ui/iconLabel/iconLabelHover';
|
||||
import { IMarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
@@ -12,7 +13,7 @@ export interface IHoverDelegateTarget extends IDisposable {
|
||||
x?: number;
|
||||
}
|
||||
|
||||
export interface IHoverDelegateOptions {
|
||||
export interface IHoverDelegateOptions extends IUpdatableHoverOptions {
|
||||
content: IMarkdownString | string | HTMLElement;
|
||||
target: IHoverDelegateTarget | HTMLElement;
|
||||
hoverPosition?: HoverPosition;
|
||||
|
||||
@@ -33,6 +33,21 @@ export function setupNativeHover(htmlElement: HTMLElement, tooltip: string | ITo
|
||||
export type IHoverContent = string | ITooltipMarkdownString | HTMLElement | undefined;
|
||||
type IResolvedHoverContent = IMarkdownString | string | HTMLElement | undefined;
|
||||
|
||||
/**
|
||||
* Copied from src\vs\workbench\services\hover\browser\hover.ts
|
||||
* @deprecated Use IHoverService
|
||||
*/
|
||||
export interface IHoverAction {
|
||||
label: string;
|
||||
commandId: string;
|
||||
iconClass?: string;
|
||||
run(target: HTMLElement): void;
|
||||
}
|
||||
|
||||
export interface IUpdatableHoverOptions {
|
||||
actions?: IHoverAction[];
|
||||
linkHandler?(url: string): void;
|
||||
}
|
||||
|
||||
export interface ICustomHover extends IDisposable {
|
||||
|
||||
@@ -49,7 +64,7 @@ export interface ICustomHover extends IDisposable {
|
||||
/**
|
||||
* Updates the contents of the hover.
|
||||
*/
|
||||
update(tooltip: IHoverContent): void;
|
||||
update(tooltip: IHoverContent, options?: IUpdatableHoverOptions): void;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +76,7 @@ class UpdatableHoverWidget implements IDisposable {
|
||||
constructor(private hoverDelegate: IHoverDelegate, private target: IHoverDelegateTarget | HTMLElement, private fadeInAnimation: boolean) {
|
||||
}
|
||||
|
||||
async update(content: IHoverContent, focus?: boolean): Promise<void> {
|
||||
async update(content: IHoverContent, focus?: boolean, options?: IUpdatableHoverOptions): Promise<void> {
|
||||
if (this._cancellationTokenSource) {
|
||||
// there's an computation ongoing, cancel it
|
||||
this._cancellationTokenSource.dispose(true);
|
||||
@@ -99,10 +114,10 @@ class UpdatableHoverWidget implements IDisposable {
|
||||
}
|
||||
}
|
||||
|
||||
this.show(resolvedContent, focus);
|
||||
this.show(resolvedContent, focus, options);
|
||||
}
|
||||
|
||||
private show(content: IResolvedHoverContent, focus?: boolean): void {
|
||||
private show(content: IResolvedHoverContent, focus?: boolean, options?: IUpdatableHoverOptions): void {
|
||||
const oldHoverWidget = this._hoverWidget;
|
||||
|
||||
if (this.hasContent(content)) {
|
||||
@@ -111,7 +126,8 @@ class UpdatableHoverWidget implements IDisposable {
|
||||
target: this.target,
|
||||
showPointer: this.hoverDelegate.placement === 'element',
|
||||
hoverPosition: HoverPosition.BELOW,
|
||||
skipFadeInAnimation: !this.fadeInAnimation || !!oldHoverWidget // do not fade in if the hover is already showing
|
||||
skipFadeInAnimation: !this.fadeInAnimation || !!oldHoverWidget, // do not fade in if the hover is already showing
|
||||
...options
|
||||
};
|
||||
|
||||
this._hoverWidget = this.hoverDelegate.showHover(hoverOptions, focus);
|
||||
@@ -142,7 +158,7 @@ class UpdatableHoverWidget implements IDisposable {
|
||||
}
|
||||
}
|
||||
|
||||
export function setupCustomHover(hoverDelegate: IHoverDelegate, htmlElement: HTMLElement, content: IHoverContent): ICustomHover {
|
||||
export function setupCustomHover(hoverDelegate: IHoverDelegate, htmlElement: HTMLElement, content: IHoverContent, options?: IUpdatableHoverOptions): ICustomHover {
|
||||
let hoverPreparation: IDisposable | undefined;
|
||||
|
||||
let hoverWidget: UpdatableHoverWidget | undefined;
|
||||
@@ -163,7 +179,7 @@ export function setupCustomHover(hoverDelegate: IHoverDelegate, htmlElement: HTM
|
||||
return new TimeoutTimer(async () => {
|
||||
if (!hoverWidget || hoverWidget.isDisposed) {
|
||||
hoverWidget = new UpdatableHoverWidget(hoverDelegate, target || htmlElement, delay > 0);
|
||||
await hoverWidget.update(content, focus);
|
||||
await hoverWidget.update(content, focus, options);
|
||||
}
|
||||
}, delay);
|
||||
};
|
||||
@@ -208,9 +224,9 @@ export function setupCustomHover(hoverDelegate: IHoverDelegate, htmlElement: HTM
|
||||
hide: () => {
|
||||
hideHover(true, true);
|
||||
},
|
||||
update: async newContent => {
|
||||
update: async (newContent, hoverOptions) => {
|
||||
content = newContent;
|
||||
await hoverWidget?.update(content);
|
||||
await hoverWidget?.update(content, undefined, hoverOptions);
|
||||
},
|
||||
dispose: () => {
|
||||
mouseOverDomEmitter.dispose();
|
||||
|
||||
@@ -351,8 +351,7 @@
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.settings-editor > .settings-body .settings-tree-container .setting-item-contents .setting-item-title .setting-item-ignored .codicon,
|
||||
.settings-editor > .settings-body .settings-tree-container .setting-item-contents .setting-item-title .setting-item-default-overridden .codicon {
|
||||
.settings-editor > .settings-body .settings-tree-container .setting-item-contents .setting-item-title .codicon {
|
||||
vertical-align: middle;
|
||||
padding-left: 1px;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { IHoverDelegate, IHoverDelegateOptions } from 'vs/base/browser/ui/iconLabel/iconHoverDelegate';
|
||||
import { setupCustomHover } from 'vs/base/browser/ui/iconLabel/iconLabelHover';
|
||||
import { ITooltipMarkdownString, IUpdatableHoverOptions, setupCustomHover } from 'vs/base/browser/ui/iconLabel/iconLabelHover';
|
||||
import { SimpleIconLabel } from 'vs/base/browser/ui/iconLabel/simpleIconLabel';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
@@ -30,6 +30,7 @@ export interface ISettingOverrideClickEvent {
|
||||
export class SettingsTreeIndicatorsLabel {
|
||||
private indicatorsContainerElement: HTMLElement;
|
||||
private scopeOverridesElement: HTMLElement;
|
||||
private scopeOverridesLabel: SimpleIconLabel;
|
||||
private syncIgnoredElement: HTMLElement;
|
||||
private defaultOverrideIndicatorElement: HTMLElement;
|
||||
private hoverDelegate: IHoverDelegate;
|
||||
@@ -42,7 +43,9 @@ export class SettingsTreeIndicatorsLabel {
|
||||
this.indicatorsContainerElement = DOM.append(container, $('.misc-label'));
|
||||
this.indicatorsContainerElement.style.display = 'inline';
|
||||
|
||||
this.scopeOverridesElement = this.createScopeOverridesElement();
|
||||
const scopeOverridesIndicator = this.createScopeOverridesIndicator();
|
||||
this.scopeOverridesElement = scopeOverridesIndicator.element;
|
||||
this.scopeOverridesLabel = scopeOverridesIndicator.label;
|
||||
this.syncIgnoredElement = this.createSyncIgnoredElement();
|
||||
this.defaultOverrideIndicatorElement = this.createDefaultOverrideIndicator();
|
||||
|
||||
@@ -55,16 +58,17 @@ export class SettingsTreeIndicatorsLabel {
|
||||
};
|
||||
}
|
||||
|
||||
private createScopeOverridesElement(): HTMLElement {
|
||||
private createScopeOverridesIndicator(): { element: HTMLElement; label: SimpleIconLabel } {
|
||||
const otherOverridesElement = $('span.setting-item-overrides');
|
||||
return otherOverridesElement;
|
||||
const otherOverridesLabel = new SimpleIconLabel(otherOverridesElement);
|
||||
return { element: otherOverridesElement, label: otherOverridesLabel };
|
||||
}
|
||||
|
||||
private createSyncIgnoredElement(): HTMLElement {
|
||||
const syncIgnoredElement = $('span.setting-item-ignored');
|
||||
const syncIgnoredLabel = new SimpleIconLabel(syncIgnoredElement);
|
||||
syncIgnoredLabel.text = '$(info) ' + localize('extensionSyncIgnoredLabel', 'Not synced');
|
||||
const syncIgnoredHoverContent = localize('syncIgnoredTitle', "Settings sync does not sync this setting");
|
||||
const syncIgnoredHoverContent = localize('syncIgnoredTitle', "This setting is ignored during sync");
|
||||
setupCustomHover(this.hoverDelegate, syncIgnoredElement, syncIgnoredHoverContent);
|
||||
return syncIgnoredElement;
|
||||
}
|
||||
@@ -106,28 +110,58 @@ export class SettingsTreeIndicatorsLabel {
|
||||
this.scopeOverridesElement.style.display = 'none';
|
||||
if (element.overriddenScopeList.length) {
|
||||
this.scopeOverridesElement.style.display = 'inline';
|
||||
const otherOverridesLabel = element.isConfigured ?
|
||||
localize('alsoConfiguredIn', "Also modified in") :
|
||||
localize('configuredIn', "Modified in");
|
||||
|
||||
DOM.append(this.scopeOverridesElement, $('span', undefined, `${otherOverridesLabel}: `));
|
||||
|
||||
for (let i = 0; i < element.overriddenScopeList.length; i++) {
|
||||
const view = DOM.append(this.scopeOverridesElement, $('a.modified-scope', undefined, element.overriddenScopeList[i]));
|
||||
|
||||
if (i !== element.overriddenScopeList.length - 1) {
|
||||
DOM.append(this.scopeOverridesElement, $('span', undefined, ', '));
|
||||
}
|
||||
if (element.overriddenScopeList.length === 1) {
|
||||
// Just show all the text in the label.
|
||||
const prefaceText = element.isConfigured ?
|
||||
localize('alsoConfiguredIn', "Also modified in") :
|
||||
localize('configuredIn', "Modified in");
|
||||
this.scopeOverridesLabel.text = `${prefaceText}: `;
|
||||
|
||||
const firstScope = element.overriddenScopeList[0];
|
||||
const view = DOM.append(this.scopeOverridesElement, $('a.modified-scope', undefined, firstScope));
|
||||
elementDisposables.add(
|
||||
DOM.addStandardDisposableListener(view, DOM.EventType.CLICK, (e: IMouseEvent) => {
|
||||
onDidClickOverrideElement.fire({
|
||||
targetKey: element.setting.key,
|
||||
scope: element.overriddenScopeList[i]
|
||||
scope: firstScope
|
||||
});
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}));
|
||||
} else {
|
||||
// Show most of the text in a custom hover.
|
||||
let scopeOverridesLabelText = '$(info) ';
|
||||
scopeOverridesLabelText += element.isConfigured ?
|
||||
localize('alsoConfiguredElsewhere', "Also modified elsewhere") :
|
||||
localize('configuredElsewhere', "Modified elsewhere");
|
||||
this.scopeOverridesLabel.text = scopeOverridesLabelText;
|
||||
|
||||
const prefaceText = element.isConfigured ?
|
||||
localize('alsoModifiedInScopes', "The setting has also been modified in the following scopes:") :
|
||||
localize('modifiedInScopes', "The setting has been modified in the following scopes:");
|
||||
let contentMarkdownString = prefaceText;
|
||||
let contentFallback = prefaceText;
|
||||
for (const scope of element.overriddenScopeList) {
|
||||
contentMarkdownString += `\n- [${scope}](${scope})`;
|
||||
contentFallback += `\n• ${scope}`;
|
||||
}
|
||||
const content: ITooltipMarkdownString = {
|
||||
markdown: {
|
||||
value: contentMarkdownString,
|
||||
isTrusted: false,
|
||||
supportHtml: false
|
||||
},
|
||||
markdownNotSupportedFallback: contentFallback
|
||||
};
|
||||
const options: IUpdatableHoverOptions = {
|
||||
linkHandler: (scope: string) => {
|
||||
onDidClickOverrideElement.fire({
|
||||
targetKey: element.setting.key,
|
||||
scope
|
||||
});
|
||||
}
|
||||
};
|
||||
setupCustomHover(this.hoverDelegate, this.scopeOverridesElement, content, options);
|
||||
}
|
||||
}
|
||||
this.render();
|
||||
@@ -173,7 +207,7 @@ export function getIndicatorsLabelAriaLabel(element: SettingsTreeSettingElement,
|
||||
// Add sync ignored text
|
||||
const ignoredSettings = getIgnoredSettings(getDefaultIgnoredSettings(), configurationService);
|
||||
if (ignoredSettings.includes(element.setting.key)) {
|
||||
ariaLabelSections.push(localize('syncIgnoredTitle', "Settings sync does not sync this setting"));
|
||||
ariaLabelSections.push(localize('syncIgnoredTitle', "This setting is ignored during sync"));
|
||||
}
|
||||
|
||||
// Add default override indicator text
|
||||
|
||||
Reference in New Issue
Block a user