VS代码-在自定义ViewsContainer中更新TreeView中的图标

时间:2019-04-05 02:53:59

标签: typescript visual-studio-code vscode-extensions

自从这篇文章以来,我取得了一些进展: Duplicate TreeView Schema is VS Code Extension

此后,我已将代码上传到此仓库:

https://github.com/trebleCode/dxdevcheck.git

我能够在我的自定义viewsContainers设置中将静态JSON文件的内容放入所需的视图中。我的想法是激活该视图,根据具有未定义iconPath值的JSON内容将项目放入视图,以便在单击刷新按钮时运行某些功能,并检查这些项目是否被视为“已配置”,如果是这样,请使用一个指示已配置或未配置的图标来更新它们。

我现在的问题是,我试图找出为什么当我尝试使用一组新的对象再次返回视图时,refresh()上存在的TreeDataViewProvider方法不会更新那些图标的原因在项目中确实具有.svg文件的值。

只需克隆存储库,从克隆的目录中运行npm i,然后按 F5 即可运行。

一个闪电图标将出现在左侧面板上,单击该图标将加载一个标记为VALIDATE的新菜单。下面是四个可扩展/可折叠的项目,每个都有两个孩子。当鼠标悬停在该菜单的右上方时,将显示一个圆形图标,指示“验证事物!”。单击后,这会将ShowInformationMessage模态放在右下角。

这是validateMenu.ts中ValidateMenuProvider类中的refresh()方法。我已经在该部分中注释掉了我尝试过的代码,无法理解为什么它的行为方式如此。

我想我正在尝试在扩展名中的错误位置实现图标更新,因此任何指针都值得赞赏。

我的课:

import * as vscode from "vscode";
import * as validateMenuItems from "./validateMenu.json";
import * as path from "path";
import * as customUtils from "./customUtils";

export class ValidateMenuProvider implements vscode.TreeDataProvider<ValidateMenu> {
    private _onDidChangeTreeData: vscode.EventEmitter<ValidateMenu | undefined> = new vscode.EventEmitter<ValidateMenu | undefined>();
    readonly onDidChangeTreeData: vscode.Event<ValidateMenu | undefined> = this._onDidChangeTreeData.event;

    constructor() {}

    refresh() {
        // Why does this not work to update icons?
        vscode.window.showInformationMessage('Refresh button clicked!');
        return this.getValidateMenu(true);
        //
    }

    getTreeItem(element?: ValidateMenu): vscode.TreeItem {
        return element;
    }

    getChildren(element?: any, withIcons?: boolean): ValidateMenu[] {
        if(element) {
            return element.children;
        }
        else {
            return this.getValidateMenu();
        }
    }

    getValidateMenu(withIcons?: boolean): ValidateMenu[] {
        const toChild = (label: string, icon?: any): ValidateMenu => { return new ValidateMenu(label,vscode.TreeItemCollapsibleState.None);};

        function getMenusFromParent(target: any) {
            let childrenArray: any = [];

            for(let i in target) {
                let currentChild: string = target[i].name;
                let currentConvertedChild = toChild(currentChild);

                if(withIcons === true) {
                    let configCheck = currentConvertedChild.isConfigured(target[i].name);

                    if(configCheck === true) {
                        currentConvertedChild.setConfiguredIcon();
                    }
                    else if(configCheck === false) {
                        currentConvertedChild.setErrorIcon();
                    }
                }
                childrenArray.push(currentConvertedChild);
            }

            return childrenArray;
        }

        function createMenu(label: string, target: any) {
            let childData = getMenusFromParent(target);
            return new ValidateMenu(label, vscode.TreeItemCollapsibleState.Expanded, childData);
        }

        let headings = Object(validateMenuItems.children);
        let child1 = headings['child1'];
        let child2 = headings['child2'];
        let child3 = headings['child3'];
        let child4 = headings['child4'];

        let menus: any = [];

        menus.push(createMenu('child1', child1));
        menus.push(createMenu('child2', child2));
        menus.push(createMenu('child3', child3));
        menus.push(createMenu('child4', child4));

        return menus;
    }
}


export class ValidateMenu extends vscode.TreeItem {
    constructor(
        public readonly label: string,
        public readonly collapsibleState: vscode.TreeItemCollapsibleState,
        public children?: ValidateMenu[],
        public readonly command?: vscode.Command,
        public iconPath?: { light: string, dark: string }
    ) {
        super(label,collapsibleState);
    }

    setConfiguredIcon(): void {
        let newLightIcon: any;
        let newDarkIcon: any;

        newLightIcon = path.join(__filename, '..', '..', 'resources', 'light', 'checkmark.svg');
        newDarkIcon = path.join(__filename, '..', '..', 'resources', 'dark', 'checkmark2.svg');

        if(this.iconPath === undefined) {
            this.iconPath = {light: newLightIcon, dark: newDarkIcon};
        }
        else {
            this.iconPath = {light: newLightIcon, dark: newDarkIcon};
        }
    }

    setErrorIcon(): void {
        let newLightIcon: any;
        let newDarkIcon: any;

        newLightIcon = path.join(__filename, '..', '..', 'resources', 'light', 'confused2.svg');
        newDarkIcon = path.join(__filename, '..', '..', 'resources', 'dark', 'confused.svg');

        if(this.iconPath === undefined) {
            this.iconPath = {light: newLightIcon, dark: newDarkIcon};
        }
        else {
            this.iconPath = {light: newLightIcon, dark: newDarkIcon};
        }
    }

    isConfigured(name: string): boolean {
        if(customUtils.checkIsConfigured(name) === true) {
            return true;
        }
        else {
            return false;
        }
    }
}

我的静态JSON文件:

{
    "name": "root",
    "children": {
        "child1": [
            {"id": "id1", "name": "child1name1"},
            {"id": "id2", "name": "child2name2"}
        ],
        "child2": [
            {"id": "id1", "name": "child2name1"},
            {"id": "id2", "name": "child2name2"}
        ],
        "child3": [
            {"id": "id1", "name": "child3name1"},
            {"id": "id2", "name": "child3name2"}
        ],
        "child4": [
            {"id": "id1", "name": "child4name1"},
            {"id": "id2", "name": "child5name2"}
        ]
    }
}

还有一些我从一些导入函数(customUtils.ts)中调用的帮助程序实用程序:

export function checkIsConfigured(name: string): boolean {
     let isConfigured: boolean;
    switch (name) {
        case 'child1':
                isConfigured = checkChild1();
            break;
        case 'child2':
             isConfigured = checkChild2();
            break;
        case 'child1':
             isConfigured = checkChild3();
            break;
        case 'child1':
             isConfigured = checkChild4();
            break;
    }
    return isConfigured;
}

export function checkChild1() {
    return true;
}

export function checkChild2() {
    return false;
}

export function checkChild3() {
    return true;
}

export function checkChild4() {
    return false;
}

最后,package.json:

{
    "name": "myview",
    "displayName": "MYVIEW",
    "description": "checks dev things",
    "version": "0.0.2",
    "publisher": "someperson",
    "engines": {
        "vscode": "^1.28.0"
    },
    "categories": [
        "Other"
    ],
    "activationEvents": [
        "onView:validateMenu"
    ],
    "main": "./out/extension.js",
    "contributes": {
        "viewsContainers": {
            "activitybar": [
                {
                    "id": "myview",
                    "title": "My Custom View Container",
                    "icon": "resources/bolt.svg"
                }
            ]
        },
        "views": {
            "myview": [
                {
                    "id": "validateMenu",
                    "name": "Validate"
                }
            ]
        },
        "commands": [
            {
                "command": "validateMenu.refreshList",
                "title": "Validate the things!",
                "icon": "resources/spinner.svg"
            }
        ],
        "menus": {
            "view/title": [
                {
                    "command": "validateMenu.refreshList",
                    "when": "view == validateMenu",
                    "group": "navigation"
                }
            ]
        }
    },
    "scripts": {
        "vscode:prepublish": "npm run compile",
        "compile": "tsc -p ./",
        "watch": "tsc -watch -p ./",
        "postinstall": "node ./node_modules/vscode/bin/install",
        "test": "npm run compile && node ./node_modules/vscode/bin/test"
    },
    "devDependencies": {
        "@types/mocha": "^2.2.42",
        "@types/node": "^10.12.21",
        "tslint": "^5.12.1",
        "typescript": "^3.3.1",
        "vscode": "^1.1.28"
    },
    "dependencies": {}
}

1 个答案:

答案 0 :(得分:1)

要改变图标,需要在 package.json 中设置图标路径,然后设置 context 值,当 refresh 方法执行时,该值将被评估使用 iconPath 调用或创建 TreeItem,然后调用刷新方法。

前者的例子:

  "menus": {
    "view/title": [{
      "command": "nodeDependencies.refreshEntry",
      "when": "view == nodeDependencies && shouldRefresh",
      "group": "navigation"
    }]
  }
vscode.commands.executeCommand('setContext', 'shouldRefresh', true);