From 0da607307df38da18ec6b70906b56aaac9504e06 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 9 Oct 2018 22:41:32 +0200 Subject: [PATCH] markers: filter with highlights --- src/vs/base/browser/ui/tree/abstractTree.ts | 15 +-- src/vs/base/browser/ui/tree/dataTree.ts | 27 +++-- src/vs/base/browser/ui/tree/tree.ts | 11 ++ src/vs/platform/list/browser/listService.ts | 5 +- .../electron-browser/markersTreeViewer.ts | 102 ++++++++++-------- 5 files changed, 92 insertions(+), 68 deletions(-) diff --git a/src/vs/base/browser/ui/tree/abstractTree.ts b/src/vs/base/browser/ui/tree/abstractTree.ts index 2915ad1a381..9c3966683bc 100644 --- a/src/vs/base/browser/ui/tree/abstractTree.ts +++ b/src/vs/base/browser/ui/tree/abstractTree.ts @@ -11,7 +11,7 @@ import { append, $ } from 'vs/base/browser/dom'; import { Event, Relay, chain, mapEvent } from 'vs/base/common/event'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; -import { ITreeModel, ITreeNode } from 'vs/base/browser/ui/tree/tree'; +import { ITreeModel, ITreeNode, ITreeRenderer } from 'vs/base/browser/ui/tree/tree'; import { ISpliceable } from 'vs/base/common/sequence'; import { IIndexTreeModelOptions } from 'vs/base/browser/ui/tree/indexTreeModel'; import { memoize } from 'vs/base/common/decorators'; @@ -72,11 +72,6 @@ function renderDefaultTwistie(node: ITreeNode, twistie: HTMLElement): } } -export interface ITreeRenderer extends IRenderer { - renderTwistie?(element: TElement, twistieElement: HTMLElement): boolean; - onDidChangeTwistieState?: Event; -} - class TreeRenderer implements IRenderer, ITreeListTemplateData> { readonly templateId: string; @@ -85,7 +80,7 @@ class TreeRenderer implements IRenderer, + private renderer: ITreeRenderer, onDidChangeCollapseState: Event> ) { this.templateId = renderer.templateId; @@ -113,11 +108,11 @@ class TreeRenderer implements IRenderer, index: number, templateData: ITreeListTemplateData): void { - this.renderer.disposeElement(node.element, index, templateData.templateData); + this.renderer.disposeElement(node, index, templateData.templateData); this.renderedNodes.delete(node); this.renderedElements.set(node.element); } @@ -190,7 +185,7 @@ export abstract class AbstractTree implements IDisposable constructor( container: HTMLElement, delegate: IVirtualDelegate, - renderers: ITreeRenderer[], + renderers: ITreeRenderer[], options?: ITreeOptions ) { const treeDelegate = new ComposedTreeDelegate>(delegate); diff --git a/src/vs/base/browser/ui/tree/dataTree.ts b/src/vs/base/browser/ui/tree/dataTree.ts index edb99d42585..c082233b7cf 100644 --- a/src/vs/base/browser/ui/tree/dataTree.ts +++ b/src/vs/base/browser/ui/tree/dataTree.ts @@ -3,10 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ITreeOptions, ComposedTreeDelegate, createComposedTreeListOptions, ITreeRenderer } from 'vs/base/browser/ui/tree/abstractTree'; +import { ITreeOptions, ComposedTreeDelegate, createComposedTreeListOptions } from 'vs/base/browser/ui/tree/abstractTree'; import { ObjectTree } from 'vs/base/browser/ui/tree/objectTree'; -import { IVirtualDelegate, IRenderer } from 'vs/base/browser/ui/list/list'; -import { ITreeElement, ITreeNode } from 'vs/base/browser/ui/tree/tree'; +import { IVirtualDelegate } from 'vs/base/browser/ui/list/list'; +import { ITreeElement, ITreeNode, ITreeRenderer, ITreeRenderElement } from 'vs/base/browser/ui/tree/tree'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { Emitter, Event } from 'vs/base/common/event'; import { timeout } from 'vs/base/common/async'; @@ -39,14 +39,21 @@ interface IDataTreeListTemplateData { templateData: T; } -class DataTreeRenderer implements ITreeRenderer, IDataTreeListTemplateData> { +function unpack(node: ITreeRenderElement, TFilterData>): ITreeRenderElement { + return { + get element() { return node.element.element; }, + get filterData() { return node.filterData; } + }; +} + +class DataTreeRenderer implements ITreeRenderer, TFilterData, IDataTreeListTemplateData> { readonly templateId: string; private renderedNodes = new Map, IDataTreeListTemplateData>(); private disposables: IDisposable[] = []; constructor( - private renderer: IRenderer, + private renderer: ITreeRenderer, readonly onDidChangeTwistieState: Event> ) { this.templateId = renderer.templateId; @@ -57,8 +64,8 @@ class DataTreeRenderer implements ITreeRenderer, index: number, templateData: IDataTreeListTemplateData): void { - this.renderer.renderElement(node.element, index, templateData.templateData); + renderElement(element: ITreeRenderElement, TFilterData>, index: number, templateData: IDataTreeListTemplateData): void { + this.renderer.renderElement(unpack(element), index, templateData.templateData); } renderTwistie(element: IDataTreeNode, twistieElement: HTMLElement): boolean { @@ -70,8 +77,8 @@ class DataTreeRenderer implements ITreeRenderer, index: number, templateData: IDataTreeListTemplateData): void { - this.renderer.disposeElement(node.element, index, templateData.templateData); + disposeElement(element: ITreeRenderElement, TFilterData>, index: number, templateData: IDataTreeListTemplateData): void { + this.renderer.disposeElement(unpack(element), index, templateData.templateData); } disposeTemplate(templateData: IDataTreeListTemplateData): void { @@ -97,7 +104,7 @@ export class DataTree, TFilterData = void> implements constructor( container: HTMLElement, delegate: IVirtualDelegate, - renderers: ITreeRenderer[], + renderers: ITreeRenderer[], private dataSource: IDataSource, options?: ITreeOptions ) { diff --git a/src/vs/base/browser/ui/tree/tree.ts b/src/vs/base/browser/ui/tree/tree.ts index f1b4bb3ce53..488ada3c4b2 100644 --- a/src/vs/base/browser/ui/tree/tree.ts +++ b/src/vs/base/browser/ui/tree/tree.ts @@ -5,6 +5,7 @@ import { Event } from 'vs/base/common/event'; import { Iterator } from 'vs/base/common/iterator'; +import { IRenderer } from 'vs/base/browser/ui/list/list'; export const enum TreeVisibility { Hidden, @@ -60,4 +61,14 @@ export interface ITreeModel { getParentElement(location: TRef): T | null; getFirstElementChild(location: TRef): T | null; getLastElementAncestor(location: TRef): T | null; +} + +export interface ITreeRenderElement { + readonly element: T; + readonly filterData: TFilterData | undefined; +} + +export interface ITreeRenderer extends IRenderer, TTemplateData> { + renderTwistie?(element: T, twistieElement: HTMLElement): boolean; + onDidChangeTwistieState?: Event; } \ No newline at end of file diff --git a/src/vs/platform/list/browser/listService.ts b/src/vs/platform/list/browser/listService.ts index d276a9609c6..75c937010bb 100644 --- a/src/vs/platform/list/browser/listService.ts +++ b/src/vs/platform/list/browser/listService.ts @@ -33,7 +33,8 @@ import { attachInputBoxStyler, attachListStyler, computeStyles, defaultListStyle import { IThemeService } from 'vs/platform/theme/common/themeService'; import { InputFocusedContextKey } from 'vs/platform/workbench/common/contextkeys'; import { ObjectTree } from 'vs/base/browser/ui/tree/objectTree'; -import { ITreeRenderer, ITreeOptions as ITreeOptions2 } from 'vs/base/browser/ui/tree/abstractTree'; +import { ITreeOptions as ITreeOptions2 } from 'vs/base/browser/ui/tree/abstractTree'; +import { ITreeRenderer } from 'vs/base/browser/ui/tree/tree'; export type ListWidget = List | PagedList | ITree | ObjectTree; @@ -814,7 +815,7 @@ export class WorkbenchObjectTree, TFilterData = void> constructor( container: HTMLElement, delegate: IVirtualDelegate, - renderers: ITreeRenderer[], + renderers: ITreeRenderer[], options: ITreeOptions2, @IContextKeyService contextKeyService: IContextKeyService, @IListService listService: IListService, diff --git a/src/vs/workbench/parts/markers/electron-browser/markersTreeViewer.ts b/src/vs/workbench/parts/markers/electron-browser/markersTreeViewer.ts index 5be3b01463f..4ee903af0cf 100644 --- a/src/vs/workbench/parts/markers/electron-browser/markersTreeViewer.ts +++ b/src/vs/workbench/parts/markers/electron-browser/markersTreeViewer.ts @@ -22,8 +22,7 @@ import { QuickFixAction } from 'vs/workbench/parts/markers/electron-browser/mark import { ILabelService } from 'vs/platform/label/common/label'; import { dirname } from 'vs/base/common/resources'; import { IVirtualDelegate } from 'vs/base/browser/ui/list/list'; -import { ITreeRenderer } from 'vs/base/browser/ui/tree/abstractTree'; -import { ITreeFilter, TreeVisibility, TreeFilterResult } from 'vs/base/browser/ui/tree/tree'; +import { ITreeFilter, TreeVisibility, TreeFilterResult, ITreeRenderer, ITreeRenderElement } from 'vs/base/browser/ui/tree/tree'; import { FilterOptions } from 'vs/workbench/parts/markers/electron-browser/markersFilterOptions'; import { IMatch } from 'vs/base/common/filters'; @@ -99,7 +98,33 @@ export class VirtualDelegate implements IVirtualDelegate { +const enum FilterDataType { + ResourceMarkers, + Marker, + RelatedInformation +} + +interface ResourceMarkersFilterData { + type: FilterDataType.ResourceMarkers; + uriMatches: IMatch[]; +} + +interface MarkerFilterData { + type: FilterDataType.Marker; + messageMatches: IMatch[]; + sourceMatches: IMatch[]; + codeMatches: IMatch[]; +} + +interface RelatedInformationFilterData { + type: FilterDataType.RelatedInformation; + uriMatches: IMatch[]; + messageMatches: IMatch[]; +} + +type FilterData = ResourceMarkersFilterData | MarkerFilterData | RelatedInformationFilterData; + +export class ResourceMarkersRenderer implements ITreeRenderer { constructor( @IInstantiationService protected instantiationService: IInstantiationService, @@ -123,14 +148,17 @@ export class ResourceMarkersRenderer implements ITreeRenderer, _: number, templateData: IResourceMarkersTemplateData): void { + const resourceMarkers = element.element; + const uriMatches = element.filterData && element.filterData.uriMatches || []; + if (templateData.resourceLabel instanceof FileLabel) { - templateData.resourceLabel.setFile(element.resource/* , { matches: element.uriMatches } */); + templateData.resourceLabel.setFile(resourceMarkers.resource, { matches: uriMatches }); } else { - templateData.resourceLabel.setLabel({ name: element.name, description: this.labelService.getUriLabel(dirname(element.resource), { relative: true }), resource: element.resource }/* , { matches: element.uriMatches } */); + templateData.resourceLabel.setLabel({ name: resourceMarkers.name, description: this.labelService.getUriLabel(dirname(resourceMarkers.resource), { relative: true }), resource: resourceMarkers.resource }, { matches: uriMatches }); } - templateData.count.setCount(element.markers.length/* filteredCount */); + // templateData.count.setCount(element.markers.length/* filteredCount */); } disposeElement(): void { @@ -156,7 +184,7 @@ export class FileResourceMarkersRenderer extends ResourceMarkersRenderer { } } -export class MarkerRenderer implements ITreeRenderer { +export class MarkerRenderer implements ITreeRenderer { constructor( private actionItemProvider: IActionItemProvider, @@ -177,24 +205,26 @@ export class MarkerRenderer implements ITreeRenderer, _: number, templateData: IMarkerTemplateData): void { + const marker = element.element.marker; + const sourceMatches = element.filterData && element.filterData.sourceMatches || []; + const messageMatches = element.filterData && element.filterData.messageMatches || []; + const codeMatches = element.filterData && element.filterData.codeMatches || []; templateData.icon.className = 'icon ' + MarkerRenderer.iconClassNameFor(marker); - templateData.source.set(marker.source/* , element.sourceMatches */); + templateData.source.set(marker.source, sourceMatches); dom.toggleClass(templateData.source.element, 'marker-source', !!marker.source); templateData.actionBar.clear(); - const quickFixAction = this.instantiationService.createInstance(QuickFixAction, element); + const quickFixAction = this.instantiationService.createInstance(QuickFixAction, element.element); templateData.actionBar.push([quickFixAction], { icon: true, label: false }); - templateData.description.set(marker.message/* , element.messageMatches */); + templateData.description.set(marker.message, messageMatches); templateData.description.element.title = marker.message; dom.toggleClass(templateData.code.element, 'marker-code', !!marker.code); - templateData.code.set(marker.code || ''/* , element.codeMatches */); + templateData.code.set(marker.code || '', codeMatches); templateData.lnCol.textContent = Messages.MARKERS_PANEL_AT_LINE_COL_NUMBER(marker.startLineNumber, marker.startColumn); } @@ -224,7 +254,7 @@ export class MarkerRenderer implements ITreeRenderer { +export class RelatedInformationRenderer implements ITreeRenderer { constructor( @ILabelService private labelService: ILabelService @@ -250,12 +280,16 @@ export class RelatedInformationRenderer implements ITreeRenderer, _: number, templateData: IRelatedInformationTemplateData): void { + const relatedInformation = element.element.raw; + const uriMatches = element.filterData && element.filterData.uriMatches || []; + const messageMatches = element.filterData && element.filterData.messageMatches || []; + + templateData.resourceLabel.set(paths.basename(relatedInformation.resource.fsPath), uriMatches); + templateData.resourceLabel.element.title = this.labelService.getUriLabel(relatedInformation.resource, { relative: true }); + templateData.lnCol.textContent = Messages.MARKERS_PANEL_AT_LINE_COL_NUMBER(relatedInformation.startLineNumber, relatedInformation.startColumn); + templateData.description.set(relatedInformation.message, messageMatches); + templateData.description.element.title = relatedInformation.message; } disposeElement(): void { @@ -268,30 +302,6 @@ export class RelatedInformationRenderer implements ITreeRenderer { options = new FilterOptions(); -- GitLab