提交 d778f612 编写于 作者: S Sandeep Somavarapu

#6679 Implement Markers tree view with file, count badge widgets. Show file on...

#6679 Implement Markers tree view with file, count badge widgets. Show file on click or enter on marker
上级 fe73dd17
/*---------------------------------------------------------------------------------------------
* 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 * as nls from 'vs/nls';
import winjs = require('vs/base/common/winjs.base');
import lifecycle = require('vs/base/common/lifecycle');
import actions = require('vs/base/common/actions');
import actionbar = require('vs/base/browser/ui/actionbar/actionbar');
import actionsrenderer = require('vs/base/parts/tree/browser/actionsRenderer');
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import tree = require('vs/base/parts/tree/browser/tree');
import { Resource } from 'vs/workbench/parts/markers/common/MarkersModel';
class RemoveResourceAction extends actions.Action {
constructor() {
super('remove', nls.localize('RemoveAction.label', "Remove"), 'action-remove');
}
public run(context?: any): winjs.TPromise<any> {
return (<tree.ITree>context['tree']).refresh();
}
}
export class ActionContainer implements lifecycle.IDisposable {
private cache: { [actionId:string]:actions.IAction; };
private instantiationService: IInstantiationService;
constructor(instantiationService: IInstantiationService) {
this.cache = <any> {};
this.instantiationService = instantiationService;
}
protected getAction(ctor: any, ...args: any[]): any {
var action = this.cache[ctor.ID];
if (!action) {
args.unshift(ctor);
action = this.cache[ctor.ID] = this.instantiationService.createInstance.apply(this.instantiationService, args);
}
return action;
}
public dispose(): void {
Object.keys(this.cache).forEach(k => {
this.cache[k].dispose();
});
this.cache = null;
}
}
export class ActionProvider extends ActionContainer implements actionsrenderer.IActionProvider {
constructor(@IInstantiationService instantiationService: IInstantiationService) {
super(instantiationService);
}
public hasActions(tree: tree.ITree, element: any): boolean {
return element instanceof Resource;
}
public getActions(tree: tree.ITree, element: any): winjs.TPromise<actions.IAction[]> {
return winjs.TPromise.as(this.getActionsForResource());
}
public getActionsForResource(): actions.IAction[] {
return [new RemoveResourceAction()];
}
public hasSecondaryActions(tree: tree.ITree, element: any): boolean {
return false;
}
public getSecondaryActions(tree: tree.ITree, element: any): winjs.TPromise<actions.IAction[]> {
return winjs.TPromise.as([]);
}
public getActionItem(tree: tree.ITree, element: any, action: actions.IAction): actionbar.IActionItem {
return null;
}
}
\ No newline at end of file
......@@ -14,10 +14,12 @@ import { Panel } from 'vs/workbench/browser/panel';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import Constants from 'vs/workbench/parts/markers/common/Constants';
import * as MarkersModel from 'vs/workbench/parts/markers/common/MarkersModel';
import {Controller} from 'vs/workbench/parts/markers/browser/MarkersTreeController';
import Tree = require('vs/base/parts/tree/browser/tree');
import TreeImpl = require('vs/base/parts/tree/browser/treeImpl');
import * as Viewer from 'vs/workbench/parts/markers/browser/MarkersTreeViewer';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import { ActionProvider } from 'vs/workbench/parts/markers/browser/MarkersActionProvider';
export class MarkersPanel extends Panel {
......@@ -38,10 +40,13 @@ export class MarkersPanel extends Panel {
super.create(parent);
dom.addClass(parent.getHTMLElement(), 'markers-panel');
var renderer = this.instantiationService.createInstance(Viewer.Renderer);
var actionProvider = this.instantiationService.createInstance(ActionProvider);
var renderer = this.instantiationService.createInstance(Viewer.Renderer, this.getActionRunner(), actionProvider);
var controller = this.instantiationService.createInstance(Controller, actionProvider);
this.tree = new TreeImpl.Tree(parent.getHTMLElement(), {
dataSource: new Viewer.DataSource(),
renderer: renderer,
controller: controller
}, {
indentPixels: 0,
twistiePixels: 20,
......
/*---------------------------------------------------------------------------------------------
* 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 * as errors from 'vs/base/common/errors';
import mouse = require('vs/base/browser/mouseEvent');
import keyboard = require('vs/base/browser/keyboardEvent');
import actionsrenderer = require('vs/base/parts/tree/browser/actionsRenderer');
import tree = require('vs/base/parts/tree/browser/tree');
import treedefaults = require('vs/base/parts/tree/browser/treeDefaults');
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { CommonKeybindings } from 'vs/base/common/keyCodes';
import { Marker } from 'vs/workbench/parts/markers/common/MarkersModel';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IMarker } from 'vs/platform/markers/common/markers';
export class Controller extends treedefaults.DefaultController {
private contextMenuService:IContextMenuService;
private actionProvider:actionsrenderer.IActionProvider;
constructor(actionProvider:actionsrenderer.IActionProvider,
@IContextMenuService contextMenuService: IContextMenuService,
@IWorkbenchEditorService private editorService: IWorkbenchEditorService) {
super({ clickBehavior: treedefaults.ClickBehavior.ON_MOUSE_UP });
this.actionProvider = actionProvider;
this.contextMenuService = contextMenuService;
this.downKeyBindingDispatcher.set(CommonKeybindings.SHIFT_UP_ARROW, this.onUp.bind(this));
this.downKeyBindingDispatcher.set(CommonKeybindings.SHIFT_DOWN_ARROW, this.onDown.bind(this));
this.downKeyBindingDispatcher.set(CommonKeybindings.SHIFT_PAGE_UP, this.onPageUp.bind(this));
this.downKeyBindingDispatcher.set(CommonKeybindings.SHIFT_PAGE_DOWN, this.onPageDown.bind(this));
}
protected onLeftClick(tree: tree.ITree, element: any, event: mouse.IMouseEvent): boolean {
if (this.openFileAtElement(element)) {
return true;
}
return super.onLeftClick(tree, element, event);
}
protected onEnter(tree:tree.ITree, event:keyboard.IKeyboardEvent):boolean {
super.onEnter(tree, event);
this.openFileAtElement(tree.getFocus());
return true;
}
private openFileAtElement(element: any) {
if (element instanceof Marker) {
let marker= <IMarker>element.marker;
this.editorService.openEditor({
resource: marker.resource,
options: {
selection: {
startLineNumber: marker.startLineNumber,
startColumn: marker.startColumn,
endLineNumber: marker.endLineNumber,
endColumn: marker.endColumn
}
}
}).done(null, errors.onUnexpectedError);
return true;
}
return false;
}
}
......@@ -4,20 +4,23 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as winjs from 'vs/base/common/winjs.base';
import * as paths from 'vs/base/common/paths';
import dom = require('vs/base/browser/dom');
import { IMarker } from 'vs/platform/markers/common/markers';
import tree = require('vs/base/parts/tree/browser/tree');
import { Marker, Resource } from 'vs/workbench/parts/markers/common/MarkersModel';
import {TPromise, Promise} from 'vs/base/common/winjs.base';
import * as dom from 'vs/base/browser/dom';
import {IDataSource, ITree, IRenderer} from 'vs/base/parts/tree/browser/tree';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { IActionRunner } from 'vs/base/common/actions';
import Severity from 'vs/base/common/severity';
import {IWorkspaceContextService} from 'vs/workbench/services/workspace/common/contextService';
import { getPathLabel } from 'vs/base/common/labels';
var $ = dom.emmet;
import { ActionProvider } from 'vs/workbench/parts/markers/browser/MarkersActionProvider';
import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge';
import { FileLabel } from 'vs/base/browser/ui/fileLabel/fileLabel';
import { IMarker } from 'vs/platform/markers/common/markers';
import { Marker, Resource } from 'vs/workbench/parts/markers/common/MarkersModel';
interface IResourceTemplateData {
label: HTMLElement;
file: FileLabel;
count: CountBadge;
actionBar: ActionBar;
}
interface IMarkerTemplateData {
......@@ -25,8 +28,8 @@ interface IMarkerTemplateData {
label: HTMLElement;
}
export class DataSource implements tree.IDataSource {
public getId(tree: tree.ITree, element: any): string {
export class DataSource implements IDataSource {
public getId(tree: ITree, element: any): string {
if (element instanceof Resource) {
return 'resource' + (<Resource>element).uri.toString();
}
......@@ -36,39 +39,42 @@ export class DataSource implements tree.IDataSource {
return 'root';
}
public hasChildren(tree: tree.ITree, element: any): boolean {
public hasChildren(tree: ITree, element: any): boolean {
return !(element instanceof Marker);
}
public getChildren(tree: tree.ITree, element: any): winjs.Promise {
public getChildren(tree: ITree, element: any): Promise {
if (element instanceof Resource) {
return winjs.TPromise.as((<Resource>element).markers);
return TPromise.as((<Resource>element).markers);
}
return winjs.TPromise.as(element['resources']);
return TPromise.as(element['resources']);
}
public getParent(tree: tree.ITree, element: any): winjs.Promise {
return winjs.TPromise.as(null);
public getParent(tree: ITree, element: any): Promise {
return TPromise.as(null);
}
}
export class Renderer implements tree.IRenderer {
constructor(@IWorkspaceContextService private contextService: IWorkspaceContextService
export class Renderer implements IRenderer {
constructor(private actionRunner: IActionRunner,
private actionProvider:ActionProvider,
@IWorkspaceContextService private contextService: IWorkspaceContextService
) {
}
public getHeight(tree:tree.ITree, element:any): number {
public getHeight(tree:ITree, element:any): number {
return 22;
}
public getTemplateId(tree:tree.ITree, element:any): string {
public getTemplateId(tree:ITree, element:any): string {
if (element instanceof Resource) {
return 'resource';
}
return 'marker';
}
public renderTemplate(tree: tree.ITree, templateId: string, container: HTMLElement): any {
public renderTemplate(tree: ITree, templateId: string, container: HTMLElement): any {
if ('resource' === templateId) {
return this.renderResourceTemplate(container);
} else {
......@@ -78,18 +84,24 @@ export class Renderer implements tree.IRenderer {
private renderResourceTemplate(container: HTMLElement): IResourceTemplateData {
var data: IResourceTemplateData = Object.create(null);
data.label = dom.append(container, $('.label'));
data.file = new FileLabel(container, null, this.contextService);
const badgeWrapper = dom.append(container, dom.emmet('.count-badge-wrapper'));
data.count = new CountBadge(badgeWrapper);
data.actionBar = new ActionBar(container, { actionRunner: this.actionRunner });
data.actionBar.push(this.actionProvider.getActionsForResource(), { icon: true, label: false });
return data;
}
private renderMarkerTemplate(container: HTMLElement): IMarkerTemplateData {
var data: IMarkerTemplateData = Object.create(null);
data.icon = dom.append(container, $('.marker-icon'));
data.label = dom.append(container, $('span.label'));
data.icon = dom.append(container, dom.emmet('.marker-icon'));
data.label = dom.append(container, dom.emmet('span.label'));
return data;
}
public renderElement(tree: tree.ITree, element: any, templateId: string, templateData: any): void {
public renderElement(tree: ITree, element: any, templateId: string, templateData: any): void {
if ('resource' === templateId) {
return this.renderResourceElement(tree, <Resource> element, templateData);
} else {
......@@ -97,17 +109,16 @@ export class Renderer implements tree.IRenderer {
}
}
public disposeTemplate(tree: tree.ITree, templateId: string, templateData: any): void {
}
private renderResourceElement(tree: tree.ITree, element: Resource, templateData: IResourceTemplateData) {
let fileNameElement= dom.append(templateData.label, $('span.file-name'));
fileNameElement.textContent= paths.basename(element.uri.fsPath);
let fileLocationElement= dom.append(templateData.label, $('span.file-path'));
fileLocationElement.textContent= getPathLabel(element.uri, this.contextService);
private renderResourceElement(tree: ITree, element: Resource, templateData: IResourceTemplateData) {
templateData.file.setValue(element.uri);
templateData.count.setCount(10);
templateData.actionBar.context= {
tree: tree,
element: element
};
}
private renderMarkerElement(tree: tree.ITree, element: IMarker, templateData: IMarkerTemplateData) {
private renderMarkerElement(tree: ITree, element: IMarker, templateData: IMarkerTemplateData) {
templateData.icon.className = 'icon ' + Renderer.iconClassNameFor(element);
templateData.label.textContent = element.message;
}
......@@ -125,4 +136,7 @@ export class Renderer implements tree.IRenderer {
}
return '';
}
public disposeTemplate(tree: ITree, templateId: string, templateData: any): void {
}
}
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="3 3 16 16" enable-background="new 3 3 16 16"><polygon fill="#e8e8e8" points="12.597,11.042 15.4,13.845 13.844,15.4 11.042,12.598 8.239,15.4 6.683,13.845 9.485,11.042 6.683,8.239 8.238,6.683 11.042,9.486 13.845,6.683 15.4,8.239"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="3 3 16 16" enable-background="new 3 3 16 16"><polygon fill="#424242" points="12.597,11.042 15.4,13.845 13.844,15.4 11.042,12.598 8.239,15.4 6.683,13.845 9.485,11.042 6.683,8.239 8.238,6.683 11.042,9.486 13.845,6.683 15.4,8.239"/></svg>
\ No newline at end of file
......@@ -3,16 +3,6 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.markers-panel .monaco-list-row {
line-height: 22px;
}
.markers-panel .file-path {
opacity: .7;
margin-left: .5em;
font-size: .9em;
}
.markers-panel .icon {
float: left;
display: block;
......@@ -22,6 +12,37 @@
margin-left: 4px;
}
.markers-panel > .monaco-tree .monaco-tree-row .content .monaco-file-label {
vertical-align: middle;
}
.markers-panel > .monaco-tree .monaco-tree-row .content .count-badge-wrapper {
display: block;
float: right;
margin-right: 10px;
line-height: 22px;
}
.markers-panel > .monaco-tree .monaco-tree-row:hover .content .count-badge-wrapper,
.markers-panel > .monaco-tree.focused .monaco-tree-row.focused .content .count-badge-wrapper {
display: none;
}
.markers-panel > .monaco-tree .monaco-tree-row:hover .content .monaco-action-bar,
.markers-panel > .monaco-tree.focused .monaco-tree-row.focused .content .monaco-action-bar {
display: block;
position: absolute;
top: 0;
right: 10px;
}
.markers-panel > .monaco-tree .monaco-tree-row .content .monaco-action-bar {
display: none;
}
a.action-label.icon.action-remove {
background: url("action-remove-dark.svg") center center no-repeat;
}
.markers-panel .icon.warning {
background: url('status-warning.svg') center center no-repeat;
......@@ -45,22 +66,4 @@
.vs-dark .markers-panel .icon.info:before {
background: url('status-info-inverse.svg') center center no-repeat;
}
.markers-panel .label {
display: block;
float: left;
text-overflow: ellipsis;
overflow: hidden;
/* icon: 16 + 4 + 4 */
/* line: 20 + 4 + 4 */
/* col: 20 + 4 + 4 */
/* file: 100 + 4 + 4 */
max-width: calc(100% - 24px - 200px - 20px)
}
.markers-panel .location {
float: right;
margin: 0 4px;
width: 200px;
}
}
\ No newline at end of file
......@@ -18,7 +18,7 @@ export class Marker {
export function toModel(markers: IMarker[]) {
let markersByResource: { [uri: string]: IMarker[] }= Object.create(null);
markers.forEach((marker:IMarker) => {
let uri:string= marker.resource.toString();
let uri:string= marker.resource.path;
let markers:IMarker[]= markersByResource[uri];
if (!markers) {
markers= [];
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册