Merge pull request #157516 from microsoft/benibenj/disabledTreeItem

Show TreeItem as disabled when command enablement is false
This commit is contained in:
Benjamin Simmonds 2022-08-09 09:14:03 +02:00 committed by GitHub
commit b41684837f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 54 additions and 15 deletions

View file

@ -30,6 +30,7 @@ export interface IIconLabelValueOptions {
matches?: IMatch[];
labelEscapeNewLines?: boolean;
descriptionMatches?: IMatch[];
disabledCommand?: boolean;
readonly separator?: string;
readonly domId?: string;
}
@ -124,22 +125,28 @@ export class IconLabel extends Disposable {
}
setLabel(label: string | string[], description?: string, options?: IIconLabelValueOptions): void {
const classes = ['monaco-icon-label'];
const labelClasses = ['monaco-icon-label'];
const containerClasses = ['monaco-icon-label-container'];
if (options) {
if (options.extraClasses) {
classes.push(...options.extraClasses);
labelClasses.push(...options.extraClasses);
}
if (options.italic) {
classes.push('italic');
labelClasses.push('italic');
}
if (options.strikethrough) {
classes.push('strikethrough');
labelClasses.push('strikethrough');
}
if (options.disabledCommand) {
containerClasses.push('disabled');
}
}
this.domNode.className = classes.join(' ');
this.domNode.className = labelClasses.join(' ');
this.labelContainer.className = containerClasses.join(' ');
this.setupHover(options?.descriptionTitle ? this.labelContainer : this.element, options?.title);
this.nameNode.setLabel(label, options);

View file

@ -31,6 +31,9 @@
flex-shrink: 0; /* fix for https://github.com/microsoft/vscode/issues/13787 */
}
.monaco-icon-label-container.disabled {
color: var(--vscode-disabledForeground);
}
.monaco-icon-label > .monaco-icon-label-container {
min-width: 0;
overflow: hidden;

View file

@ -10,6 +10,9 @@
position: relative;
}
.monaco-tl-row.disabled {
cursor: default;
}
.monaco-tl-indent {
height: 100%;
position: absolute;

View file

@ -696,8 +696,8 @@ class ExtHostTreeView<T> extends Disposable {
return tooltip;
}
private getCommand(disposable: DisposableStore, command?: vscode.Command): Command | undefined {
return command ? this.commands.toInternal(command, disposable) : undefined;
private getCommand(disposable: DisposableStore, command?: vscode.Command): Command & { originalId: string } | undefined {
return command ? { ...this.commands.toInternal(command, disposable), originalId: command.command } : undefined;
}
private validateTreeItem(extensionTreeItem: vscode.TreeItem) {

View file

@ -540,7 +540,8 @@ class ResourceLabelWidget extends IconLabel {
descriptionMatches: this.options?.descriptionMatches,
extraClasses: [],
separator: this.options?.separator,
domId: this.options?.domId
domId: this.options?.domId,
disabledCommand: this.options?.disabledCommand,
};
const resource = toResource(this.label);

View file

@ -150,6 +150,9 @@
-moz-osx-font-smoothing: grayscale;
}
.customview-tree .monaco-list .monaco-list-row .custom-view-tree-node-item>.custom-view-tree-node-item-icon.disabled {
opacity: 60%;
}
/* makes spinning icons square */
.customview-tree .monaco-list .monaco-list-row .custom-view-tree-node-item > .custom-view-tree-node-item-icon.codicon.codicon-modifier-spin {
padding-left: 6px;

View file

@ -35,8 +35,8 @@ import { VSDataTransfer } from 'vs/base/common/dataTransfer';
import { Command } from 'vs/editor/common/languages';
import { localize } from 'vs/nls';
import { createActionViewItem, createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { Action2, IMenu, IMenuService, MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { Action2, IMenu, IMenuService, MenuId, MenuRegistry, registerAction2 } from 'vs/platform/actions/common/actions';
import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ContextKeyExpr, IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
@ -941,7 +941,8 @@ class TreeRenderer extends Disposable implements ITreeRenderer<ITreeItem, FuzzyS
@IConfigurationService private readonly configurationService: IConfigurationService,
@ILabelService private readonly labelService: ILabelService,
@IHoverService private readonly hoverService: IHoverService,
@ITreeViewsService private readonly treeViewsService: ITreeViewsService
@ITreeViewsService private readonly treeViewsService: ITreeViewsService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
) {
super();
this._hoverDelegate = {
@ -1029,6 +1030,18 @@ class TreeRenderer extends Disposable implements ITreeRenderer<ITreeItem, FuzzyS
templateData.actionBar.clear();
templateData.icon.style.color = '';
let commandEnabled = true;
if (node.command) {
const command = CommandsRegistry.getCommand(node.command.originalId ? node.command.originalId : node.command.id);
if (command) {
const commandAction = MenuRegistry.getCommand(command.id);
const precondition = commandAction && commandAction.precondition;
if (precondition) {
commandEnabled = this.contextKeyService.contextMatchesRules(precondition);
}
}
}
if (resource) {
const fileDecorations = this.configurationService.getValue<{ colors: boolean; badges: boolean }>('explorer.decorations');
const labelResource = resource ? resource : URI.parse('missing:_icon_resource');
@ -1039,7 +1052,8 @@ class TreeRenderer extends Disposable implements ITreeRenderer<ITreeItem, FuzzyS
fileDecorations,
extraClasses: ['custom-view-tree-node-item-resourceLabel'],
matches: matches ? matches : createMatches(element.filterData),
strikethrough: treeItemLabel?.strikethrough
strikethrough: treeItemLabel?.strikethrough,
disabledCommand: !commandEnabled
});
} else {
templateData.resourceLabel.setResource({ name: label, description }, {
@ -1047,7 +1061,8 @@ class TreeRenderer extends Disposable implements ITreeRenderer<ITreeItem, FuzzyS
hideIcon: true,
extraClasses: ['custom-view-tree-node-item-resourceLabel'],
matches: matches ? matches : createMatches(element.filterData),
strikethrough: treeItemLabel?.strikethrough
strikethrough: treeItemLabel?.strikethrough,
disabledCommand: !commandEnabled
});
}
@ -1066,6 +1081,13 @@ class TreeRenderer extends Disposable implements ITreeRenderer<ITreeItem, FuzzyS
templateData.icon.style.backgroundImage = '';
}
if (!commandEnabled) {
templateData.icon.className = templateData.icon.className + ' disabled';
if (templateData.container.parentElement) {
templateData.container.parentElement.className = templateData.container.parentElement.className + ' disabled';
}
}
templateData.actionBar.context = <TreeViewItemHandleArg>{ $treeViewId: this.treeViewId, $treeItemHandle: node.handle };
const disposableStore = new DisposableStore();

View file

@ -755,7 +755,7 @@ export interface ITreeItem {
contextValue?: string;
command?: Command;
command?: Command & { originalId?: string };
children?: ITreeItem[];
@ -774,7 +774,7 @@ export class ResolvableTreeItem implements ITreeItem {
resourceUri?: UriComponents;
tooltip?: string | IMarkdownString;
contextValue?: string;
command?: Command;
command?: Command & { originalId?: string };
children?: ITreeItem[];
accessibilityInformation?: IAccessibilityInformation;
resolve: (token: CancellationToken) => Promise<void>;