From b47ebd34e188f6bb6e2d10b4203b7619da2f76f6 Mon Sep 17 00:00:00 2001 From: "tamas.kiss" Date: Thu, 30 Jun 2016 07:55:10 +0200 Subject: [PATCH] Tree decorators infrastructure created A first example is also included: gitStatusTreeDecorator Resolves #5866 Related #211 --- src/vs/base/parts/tree/browser/tree.ts | 13 ++ src/vs/base/parts/tree/browser/treeImpl.ts | 9 ++ src/vs/base/parts/tree/browser/treeView.ts | 22 ++- src/vs/workbench/browser/workbench.ts | 2 + .../parts/decorators/decoratorRegistry.ts | 46 +++++++ .../parts/decorators/treeDecorator.ts | 31 +++++ .../parts/files/browser/views/explorerView.ts | 3 + .../files/browser/views/explorerViewer.ts | 1 + .../files/browser/views/openEditorsView.ts | 3 + .../git/browser/gitStatusTreeDecorator.ts | 126 ++++++++++++++++++ .../git/browser/gitWorkbenchContributions.ts | 7 + .../git/browser/media/git.contribution.css | 57 ++++++++ 12 files changed, 308 insertions(+), 12 deletions(-) create mode 100644 src/vs/workbench/parts/decorators/decoratorRegistry.ts create mode 100644 src/vs/workbench/parts/decorators/treeDecorator.ts create mode 100644 src/vs/workbench/parts/git/browser/gitStatusTreeDecorator.ts diff --git a/src/vs/base/parts/tree/browser/tree.ts b/src/vs/base/parts/tree/browser/tree.ts index 727908f55cc1c..73b2f3ca33f36 100644 --- a/src/vs/base/parts/tree/browser/tree.ts +++ b/src/vs/base/parts/tree/browser/tree.ts @@ -12,6 +12,12 @@ import Keyboard = require('vs/base/browser/keyboardEvent'); import { INavigator } from 'vs/base/common/iterator'; import { ScrollbarVisibility } from 'vs/base/browser/ui/scrollbar/scrollableElementOptions'; +export interface IRow { + element: HTMLElement; + templateId: string; + templateData: any; +} + export interface ITree extends Events.IEventEmitter { emit(eventType:string, data?:any):void; @@ -355,6 +361,12 @@ export interface IDataSource { getParent(tree: ITree, element: any): WinJS.Promise; } +export interface IDecorator { + onActivate(tree: ITree): void; + decorate(tree: ITree, element: any, templateId: string, row: IRow): void; + dispose(): void; +} + export interface IRenderer { /** @@ -614,6 +626,7 @@ export interface IHighlightEvent { export interface ITreeConfiguration { dataSource: IDataSource; renderer?: IRenderer; + decorator?: IDecorator; controller?: IController; dnd?: IDragAndDrop; filter?: IFilter; diff --git a/src/vs/base/parts/tree/browser/treeImpl.ts b/src/vs/base/parts/tree/browser/treeImpl.ts index 4ff2a308a7a1d..8dae18ec7bc70 100644 --- a/src/vs/base/parts/tree/browser/treeImpl.ts +++ b/src/vs/base/parts/tree/browser/treeImpl.ts @@ -22,6 +22,7 @@ export class TreeContext implements _.ITreeContext { public dataSource:_.IDataSource; public renderer:_.IRenderer; public controller:_.IController; + public decorator:_.IDecorator; public dnd:_.IDragAndDrop; public filter:_.IFilter; public sorter:_.ISorter; @@ -42,7 +43,12 @@ export class TreeContext implements _.ITreeContext { this.dnd = configuration.dnd || new TreeDefaults.DefaultDragAndDrop(); this.filter = configuration.filter || new TreeDefaults.DefaultFilter(); this.sorter = configuration.sorter || null; + this.decorator = configuration.decorator || null; this.accessibilityProvider = configuration.accessibilityProvider || new TreeDefaults.DefaultAccessibilityProvider(); + + if (this.decorator) { + this.decorator.onActivate(tree); + } } } @@ -327,6 +333,9 @@ export class Tree extends Events.EventEmitter implements _.ITree { this.view.dispose(); this.view = null; } + if (this.context.decorator !== null) { + this.context.decorator.dispose(); + } super.dispose(); } diff --git a/src/vs/base/parts/tree/browser/treeView.ts b/src/vs/base/parts/tree/browser/treeView.ts index 61f19d59fc44e..77bb1e89c7b89 100644 --- a/src/vs/base/parts/tree/browser/treeView.ts +++ b/src/vs/base/parts/tree/browser/treeView.ts @@ -24,12 +24,6 @@ import _ = require('vs/base/parts/tree/browser/tree'); import { IViewItem } from 'vs/base/parts/tree/browser/treeViewModel'; import {KeyCode} from 'vs/base/common/keyCodes'; -export interface IRow { - element: HTMLElement; - templateId: string; - templateData: any; -} - function getLastScrollTime(element: HTMLElement): number { var value = element.getAttribute('last-scroll-time'); return value ? parseInt(value, 10) : 0; @@ -45,15 +39,15 @@ function removeFromParent(element: HTMLElement): void { export class RowCache implements Lifecycle.IDisposable { - private _cache: { [templateId:string]: IRow[]; }; - private scrollingRow: IRow; + private _cache: { [templateId:string]: _.IRow[]; }; + private scrollingRow: _.IRow; constructor(private context: _.ITreeContext) { this._cache = { '': [] }; this.scrollingRow = null; } - public alloc(templateId: string): IRow { + public alloc(templateId: string): _.IRow { var result = this.cache(templateId).pop(); if (!result) { @@ -73,7 +67,7 @@ export class RowCache implements Lifecycle.IDisposable { return result; } - public release(templateId: string, row: IRow): void { + public release(templateId: string, row: _.IRow): void { var lastScrollTime = getLastScrollTime(row.element); if (!lastScrollTime) { @@ -102,7 +96,7 @@ export class RowCache implements Lifecycle.IDisposable { DOM.addClass(this.scrollingRow.element, 'scrolling'); } - private cache(templateId: string): IRow[] { + private cache(templateId: string): _.IRow[] { return this._cache[templateId] || (this._cache[templateId] = []); } @@ -142,7 +136,7 @@ export class ViewItem implements IViewItem { public model: Model.Item; public id: string; - protected row: IRow; + protected row: _.IRow; public top: number; public height: number; @@ -284,6 +278,9 @@ export class ViewItem implements IViewItem { if (!skipUserRender) { this.context.renderer.renderElement(this.context.tree, this.model.getElement(), this.templateId, this.row.templateData); + if (this.context.decorator) { + this.context.decorator.decorate(this.context.tree, this.model.getElement(), this.templateId, this.row); + } } } @@ -451,6 +448,7 @@ export class TreeView extends HeightMap { filter: context.filter, sorter: context.sorter, tree: context.tree, + decorator: context.decorator, accessibilityProvider: context.accessibilityProvider, options: context.options, cache: new RowCache(context) diff --git a/src/vs/workbench/browser/workbench.ts b/src/vs/workbench/browser/workbench.ts index 6ff4717f0d834..18e67b46f7555 100644 --- a/src/vs/workbench/browser/workbench.ts +++ b/src/vs/workbench/browser/workbench.ts @@ -22,6 +22,7 @@ import {Identifiers} from 'vs/workbench/common/constants'; import {isWindows, isLinux} from 'vs/base/common/platform'; import {IOptions} from 'vs/workbench/common/options'; import {IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions} from 'vs/workbench/common/contributions'; +import {IDecoratorRegistry, Extensions as DecoratorExtensions} from 'vs/workbench/parts/decorators/decoratorRegistry'; import {IEditorRegistry, Extensions as EditorExtensions, BaseEditor} from 'vs/workbench/browser/parts/editor/baseEditor'; import {TextEditorOptions, EditorInput, EditorOptions} from 'vs/workbench/common/editor'; import {Part} from 'vs/workbench/browser/part'; @@ -397,6 +398,7 @@ export class Workbench implements IPartService { Registry.as(ActionBarExtensions.Actionbar).setInstantiationService(this.instantiationService); Registry.as(WorkbenchExtensions.Workbench).setInstantiationService(this.instantiationService); Registry.as(EditorExtensions.Editors).setInstantiationService(this.instantiationService); + Registry.as(DecoratorExtensions.Decorators).setInstantiationService(this.instantiationService); } private initSettings(): void { diff --git a/src/vs/workbench/parts/decorators/decoratorRegistry.ts b/src/vs/workbench/parts/decorators/decoratorRegistry.ts new file mode 100644 index 0000000000000..8d150186efefc --- /dev/null +++ b/src/vs/workbench/parts/decorators/decoratorRegistry.ts @@ -0,0 +1,46 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import {Registry, BaseRegistry} from 'vs/platform/platform'; +import {IConstructorSignature0} from 'vs/platform/instantiation/common/instantiation'; +import tree = require('vs/base/parts/tree/browser/tree'); + +export namespace Extensions { + export const Decorators = 'decorator.contributions.kind'; +} + +export type IDecoratorSignature = IConstructorSignature0; + +export interface IDecoratorRegistry { + + /** + * Registers a decorator to the platform that will be loaded when the workbench starts and disposed when + * the workbench shuts down. + */ + registerDecorator(decorator: IDecoratorSignature): void; + + /** + * Returns all decorators that are known to the platform. + */ + getDecorators(): tree.IDecorator[]; +} + +class DecorationsRegistry extends BaseRegistry implements IDecoratorRegistry { + + public registerDecorator(ctor: IDecoratorSignature): void { + super._register(ctor); + } + + public getDecorators(): tree.IDecorator[] { + return super._getInstances(); + } + + public setDecorators(contributions: tree.IDecorator[]): void { + super._setInstances(contributions); + } +} + +Registry.add(Extensions.Decorators, new DecorationsRegistry()); \ No newline at end of file diff --git a/src/vs/workbench/parts/decorators/treeDecorator.ts b/src/vs/workbench/parts/decorators/treeDecorator.ts new file mode 100644 index 0000000000000..2e8739cb953a0 --- /dev/null +++ b/src/vs/workbench/parts/decorators/treeDecorator.ts @@ -0,0 +1,31 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +import tree = require('vs/base/parts/tree/browser/tree'); +import lifecycle = require('vs/base/common/lifecycle'); +import {Registry} from 'vs/platform/platform'; +import {IDecoratorRegistry, Extensions as DecoratorExtensions} from 'vs/workbench/parts/decorators/decoratorRegistry'; + +export class TreeDecorator implements tree.IDecorator { + + protected decorators: tree.IDecorator[] = []; + protected toDispose: lifecycle.IDisposable[] = []; + constructor() { + } + + public onActivate(tree: tree.ITree): void { + this.decorators = Registry.as(DecoratorExtensions.Decorators).getDecorators(); + this.decorators.forEach(decorator=>decorator.onActivate(tree)); + } + + public decorate(tree: tree.ITree, element: any, templateId: string, row: tree.IRow): void { + this.decorators.forEach(decorator=>decorator.decorate(tree,element,templateId, row)); + } + + public dispose(): void { + this.decorators.forEach(decorator => decorator.dispose()); + this.toDispose.forEach(item => item.dispose()); + } +} \ No newline at end of file diff --git a/src/vs/workbench/parts/files/browser/views/explorerView.ts b/src/vs/workbench/parts/files/browser/views/explorerView.ts index e8eb8a93fd8e2..ea3b747d30a9e 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerView.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerView.ts @@ -15,6 +15,7 @@ import paths = require('vs/base/common/paths'); import {Action, IActionRunner, IAction} from 'vs/base/common/actions'; import {prepareActions} from 'vs/workbench/browser/actionBarRegistry'; import {ITree} from 'vs/base/parts/tree/browser/tree'; +import {TreeDecorator} from 'vs/workbench/parts/decorators/treeDecorator'; import {Tree} from 'vs/base/parts/tree/browser/treeImpl'; import {EditorOptions} from 'vs/workbench/common/editor'; import {LocalFileChangeEvent, IFilesConfiguration} from 'vs/workbench/parts/files/common/files'; @@ -330,6 +331,7 @@ export class ExplorerView extends CollapsibleViewletView { let dataSource = this.instantiationService.createInstance(FileDataSource); let renderer = this.instantiationService.createInstance(FileRenderer, this.viewletState, this.actionRunner); let controller = this.instantiationService.createInstance(FileController, this.viewletState); + let decorator = this.instantiationService.createInstance(TreeDecorator); let sorter = new FileSorter(); this.filter = this.instantiationService.createInstance(FileFilter); let dnd = this.instantiationService.createInstance(FileDragAndDrop); @@ -340,6 +342,7 @@ export class ExplorerView extends CollapsibleViewletView { renderer: renderer, controller: controller, sorter: sorter, + decorator: decorator, filter: this.filter, dnd: dnd, accessibilityProvider: accessibility diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index 54a1e03a7ec6f..0329e6283da91 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -261,6 +261,7 @@ export class FileRenderer extends ActionsRenderer implements IRenderer { constructor( state: FileViewletState, actionRunner: IActionRunner, + @IWorkspaceContextService private contextService: IWorkspaceContextService, @IContextViewService private contextViewService: IContextViewService ) { super({ diff --git a/src/vs/workbench/parts/files/browser/views/openEditorsView.ts b/src/vs/workbench/parts/files/browser/views/openEditorsView.ts index 026f04aa1b016..18ee2218b8c80 100644 --- a/src/vs/workbench/parts/files/browser/views/openEditorsView.ts +++ b/src/vs/workbench/parts/files/browser/views/openEditorsView.ts @@ -11,6 +11,7 @@ import {IAction, IActionRunner} from 'vs/base/common/actions'; import dom = require('vs/base/browser/dom'); import {CollapsibleState} from 'vs/base/browser/ui/splitview/splitview'; import {Tree} from 'vs/base/parts/tree/browser/treeImpl'; +import {TreeDecorator} from 'vs/workbench/parts/decorators/treeDecorator'; import {IContextMenuService} from 'vs/platform/contextview/browser/contextView'; import {IMessageService} from 'vs/platform/message/common/message'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; @@ -93,6 +94,7 @@ export class OpenEditorsView extends AdaptiveCollapsibleViewletView { const dataSource = this.instantiationService.createInstance(DataSource); const actionProvider = this.instantiationService.createInstance(ActionProvider, this.model); const renderer = this.instantiationService.createInstance(Renderer, actionProvider, this.model); + const decorator = this.instantiationService.createInstance(TreeDecorator); const controller = this.instantiationService.createInstance(Controller, actionProvider, this.model); const accessibilityProvider = this.instantiationService.createInstance(AccessibilityProvider); const dnd = this.instantiationService.createInstance(DragAndDrop); @@ -100,6 +102,7 @@ export class OpenEditorsView extends AdaptiveCollapsibleViewletView { this.tree = new Tree(this.treeContainer, { dataSource, renderer, + decorator, controller, accessibilityProvider, dnd diff --git a/src/vs/workbench/parts/git/browser/gitStatusTreeDecorator.ts b/src/vs/workbench/parts/git/browser/gitStatusTreeDecorator.ts new file mode 100644 index 0000000000000..ce08edc89323c --- /dev/null +++ b/src/vs/workbench/parts/git/browser/gitStatusTreeDecorator.ts @@ -0,0 +1,126 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +import tree = require('vs/base/parts/tree/browser/tree'); +import {IGitService, IFileStatus, Status, ModelEvents} from 'vs/workbench/parts/git/common/git'; +import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; +import lifecycle = require('vs/base/common/lifecycle'); +import URI from 'vs/base/common/uri'; +import paths = require('vs/base/common/paths'); +import {FileStat} from 'vs/workbench/parts/files/common/explorerViewModel'; +import {OpenEditor} from 'vs/workbench/parts/files/browser/views/openEditorsViewer'; +import DOM = require('vs/base/browser/dom'); + +export class GitStatusTreeDecorator implements tree.IDecorator { + protected toDispose: lifecycle.IDisposable[] = []; + constructor( + @IGitService private gitService: IGitService, + @IWorkspaceContextService private contextService: IWorkspaceContextService) { + + } + + public onActivate(tree: tree.ITree): void { + this.toDispose.push(this.gitService.getModel().addListener2(ModelEvents.MODEL_UPDATED, () => tree.refresh(tree.getInput()))); + } + + public decorate(tree: tree.ITree, element: any, templateId: string, row: tree.IRow): void { + + if (element instanceof OpenEditor) { + let fileStatus = this.getStatus(element.getResource()); + let className = this.fileStatusToClassName(fileStatus); + let child = row.element.querySelector('.open-editor .name'); + if (child instanceof HTMLElement) { + this.cleanGitClassName(child); + DOM.addClass(child, className); + } + } + if (element instanceof FileStat){ + let fileStatus = this.getStatus((element).resource); + let className = this.fileStatusToClassName(fileStatus); + let child = row.element.querySelector('.explorer-item-label'); + if (child instanceof HTMLElement) { + this.cleanGitClassName(child); + DOM.addClass(child, className); + } + } + } + + private getStatus(uri: URI) { + + const workspaceRoot = this.contextService.getWorkspace().resource.fsPath; + if (!workspaceRoot || !paths.isEqualOrParent(uri.fsPath, workspaceRoot)) { + return null; // out of workspace not yet supported + } + + const model = this.gitService.getModel(); + const repositoryRoot = model.getRepositoryRoot(); + const statusModel = model.getStatus(); + + if (!repositoryRoot || !paths.isEqualOrParent(uri.fsPath, repositoryRoot)) { + return null; // out of repository not supported + } + + const repositoryRelativePath = paths.normalize(paths.relative(repositoryRoot, uri.fsPath)); + return statusModel.getWorkingTreeStatus().find(repositoryRelativePath) || + statusModel.getIndexStatus().find(repositoryRelativePath); + } + + private cleanGitClassName(element: HTMLElement) { + DOM.removeClass(element, 'index-modified'); + DOM.removeClass(element, 'index-added'); + DOM.removeClass(element, 'index-deleted'); + DOM.removeClass(element, 'index-renamed'); + DOM.removeClass(element, 'index-copied'); + DOM.removeClass(element, 'modified'); + DOM.removeClass(element, 'deleted'); + DOM.removeClass(element, 'untracked'); + DOM.removeClass(element, 'ignored'); + DOM.removeClass(element, 'added-by-us'); + DOM.removeClass(element, 'added-by-them'); + DOM.removeClass(element, 'deleted-by-us'); + DOM.removeClass(element, 'deleted-by-them'); + DOM.removeClass(element, 'both-added'); + DOM.removeClass(element, 'both-deleted'); + DOM.removeClass(element, 'both-modified'); + } + + private fileStatusToClassName(stat: IFileStatus): string { + let result = ''; + if (stat === null || stat === undefined) { + return result; + } + let status: Status = stat.getStatus(); + switch (status) { + case Status.INDEX_MODIFIED: result = 'index-modified'; break; + case Status.INDEX_ADDED: result = 'index-added'; break; + case Status.INDEX_DELETED: result = 'index-deleted'; break; + case Status.INDEX_RENAMED: result = 'index-renamed'; break; + case Status.INDEX_COPIED: result = 'index-copied'; break; + case Status.MODIFIED: result = 'modified'; break; + case Status.DELETED: result = 'deleted'; break; + case Status.UNTRACKED: result = 'untracked'; break; + case Status.IGNORED: result = 'ignored'; break; + case Status.ADDED_BY_US: result = 'added-by-us'; break; + case Status.ADDED_BY_THEM: result = 'added-by-them'; break; + case Status.DELETED_BY_US: result = 'deleted-by-us'; break; + case Status.DELETED_BY_THEM: result = 'deleted-by-them'; break; + case Status.BOTH_ADDED: result = 'both-added'; break; + case Status.BOTH_DELETED: result = 'both-deleted'; break; + case Status.BOTH_MODIFIED: result = 'both-modified'; break; + } + + return result; + } + + public dispose(): void { + this.toDispose.forEach(item => item.dispose()); + } + + + public getId() { + return 'workbench.tree.git.decorator'; + } + +} \ No newline at end of file diff --git a/src/vs/workbench/parts/git/browser/gitWorkbenchContributions.ts b/src/vs/workbench/parts/git/browser/gitWorkbenchContributions.ts index 0a4f9fc75065e..90091643f0bd1 100644 --- a/src/vs/workbench/parts/git/browser/gitWorkbenchContributions.ts +++ b/src/vs/workbench/parts/git/browser/gitWorkbenchContributions.ts @@ -44,6 +44,9 @@ import {IEditorGroupService} from 'vs/workbench/services/group/common/groupServi import IGitService = git.IGitService; +import {GitStatusTreeDecorator} from 'vs/workbench/parts/git/browser/gitStatusTreeDecorator'; +import {IDecoratorRegistry, Extensions as DecoratorExtensions} from 'vs/workbench/parts/decorators/decoratorRegistry'; + export class StatusUpdater implements ext.IWorkbenchContribution { static ID = 'vs.git.statusUpdater'; @@ -540,4 +543,8 @@ export function registerContributions(): void { } } }); + + platform.Registry.as(DecoratorExtensions.Decorators).registerDecorator( + GitStatusTreeDecorator + ); } diff --git a/src/vs/workbench/parts/git/browser/media/git.contribution.css b/src/vs/workbench/parts/git/browser/media/git.contribution.css index 6f8d3b642777a..c306dbc8ba078 100644 --- a/src/vs/workbench/parts/git/browser/media/git.contribution.css +++ b/src/vs/workbench/parts/git/browser/media/git.contribution.css @@ -228,4 +228,61 @@ .monaco-shell .monaco-workbench.mac .git-statusbar-group > .git-statusbar-branch-item.headless { font-weight: 300; /* makes the italic font appear the same as normal */ +} + + +.monaco-tree-row:not(.selected):not(.highlighted) .index-renamed, +.monaco-tree-row:not(.selected):not(.highlighted) .modified, +.monaco-tree-row:not(.selected):not(.highlighted) .index-modified, +.monaco-tree-row:not(.selected):not(.highlighted) .both-modified { + color: rgba(0, 122, 204, 1); + font-weight: 500; +} +.vs-dark .monaco-tree-row:not(.selected):not(.highlighted) .index-renamed, +.vs-dark .monaco-tree-row:not(.selected):not(.highlighted) .modified, +.vs-dark .monaco-tree-row:not(.selected):not(.highlighted) .index-modified, +.vs-dark .monaco-tree-row:not(.selected):not(.highlighted) .both-modified, +.hc-black .monaco-tree-row:not(.selected):not(.highlighted) .index-renamed, +.hc-black .monaco-tree-row:not(.selected):not(.highlighted) .modified, +.hc-black .monaco-tree-row:not(.selected):not(.highlighted) .index-modified, +.hc-black .monaco-tree-row:not(.selected):not(.highlighted) .both-modified { + color: rgba(0, 188, 242, 1); + font-weight: 500; +} + +.monaco-tree-row:not(.selected):not(.highlighted) .index-copied, +.monaco-tree-row:not(.selected):not(.highlighted) .added_by-us, +.monaco-tree-row:not(.selected):not(.highlighted) .added_by-them, +.monaco-tree-row:not(.selected):not(.highlighted) .index-added, +.monaco-tree-row:not(.selected):not(.highlighted) .both-added { + color: rgba(45, 136, 62, 1); + font-weight: 500; +} + +.vs-dark .monaco-tree-row:not(.selected):not(.highlighted) .index-copied, +.vs-dark .monaco-tree-row:not(.selected):not(.highlighted) .added_by-us, +.vs-dark .monaco-tree-row:not(.selected):not(.highlighted) .added_by-them, +.vs-dark .monaco-tree-row:not(.selected):not(.highlighted) .index-added, +.vs-dark .monaco-tree-row:not(.selected):not(.highlighted) .both-added, +.hc-black .monaco-tree-row:not(.selected):not(.highlighted) .index-copied, +.hc-black .monaco-tree-row:not(.selected):not(.highlighted) .added_by-us, +.hc-black .monaco-tree-row:not(.selected):not(.highlighted) .added_by-them, +.hc-black .monaco-tree-row:not(.selected):not(.highlighted) .index-added, +.hc-black .monaco-tree-row:not(.selected):not(.highlighted) .both-added { + color: rgba(127, 186, 0, 1); + font-weight: 500; +} + +.monaco-tree-row:not(.selected):not(.highlighted) .untracked, +.monaco-tree-row:not(.selected):not(.highlighted) .ignored { + font-weight: 500; +} + +.monaco-tree-row:not(.selected):not(.highlighted) .deleted, +.monaco-tree-row:not(.selected):not(.highlighted) .index-deleted, +.monaco-tree-row:not(.selected):not(.highlighted) .deleted-by-us, +.monaco-tree-row:not(.selected):not(.highlighted) .deleted-by-them, +.monaco-tree-row:not(.selected):not(.highlighted) .both-deleted { + color: rgba(185, 19, 26, 1); + font-weight: 500; } \ No newline at end of file