Allow to switch flat/hierarchical view of projects & modules (#202)

* Add config to specify the way of viewing maven projects.

* Organize Maven project nodes according to the config.

* Add commands to switch between flat/hierarchical view.

* Add description for commands.
This commit is contained in:
Yan Zhang 2018-12-28 16:20:26 +08:00 коммит произвёл GitHub
Родитель c1b8ed5f81
Коммит 8ba0d51854
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
12 изменённых файлов: 256 добавлений и 44 удалений

Просмотреть файл

@ -145,6 +145,24 @@
"command": "maven.plugin.execute",
"title": "%contributes.commands.maven.plugin.execute%",
"category": "Maven"
},
{
"command": "maven.view.flat",
"title": "%contributes.commands.maven.view.flat%",
"category": "Maven",
"icon": {
"light": "resources/light/view-flat.svg",
"dark": "resources/dark/view-flat.svg"
}
},
{
"command": "maven.view.hierarchical",
"title": "%contributes.commands.maven.view.hierarchical%",
"category": "Maven",
"icon": {
"light": "resources/light/view-hierarchical.svg",
"dark": "resources/dark/view-hierarchical.svg"
}
}
],
"views": {
@ -222,6 +240,16 @@
}
],
"view/title": [
{
"command": "maven.view.flat",
"when": "view == mavenProjects && config.maven.view != flat",
"group": "navigation@0a"
},
{
"command": "maven.view.hierarchical",
"when": "view == mavenProjects && config.maven.view != hierarchical",
"group": "navigation@0b"
},
{
"command": "maven.archetype.generate",
"when": "view == mavenProjects",
@ -375,6 +403,16 @@
"default": false,
"scope": "window",
"description": "%configuration.maven.completion.enabled%"
},
"maven.view": {
"type": "string",
"enum": [
"flat",
"hierarchical"
],
"default": "flat",
"scope": "resourec",
"description": "%configuration.maven.view%"
}
}
}

Просмотреть файл

@ -9,15 +9,17 @@
"contributes.commands.maven.history": "History ...",
"contributes.commands.maven.goal.execute": "Execute commands",
"contributes.commands.maven.plugin.execute": "Execute",
"contributes.commands.maven.view.hierarchical": "Switch to hierarchical view",
"contributes.commands.maven.view.flat": "Switch to flat view",
"contributes.views.explorer.mavenProjects": "Maven Projects",
"configuration.maven.excludedFolders": "Specifies filepath pattern of folders to exclude while searching for Maven projects.",
"configuration.maven.executable.preferMavenWrapper":"Specifies whether you prefer to use Maven wrapper. If true, it tries using 'mvnw' in root folder by default if the file econfiguration.xists. Otherwise it tries 'mvn' in PATH instead.",
"configuration.maven.executable.path":"Specifies absolute path of your mvn executable. When this value is empty, it tries using 'mvn' or 'mvnw' according to value of 'maven.executeble.preferMavenWapper'. Note that a relative path is not suggested, but if you do specify one, the absolute path will be resolved from your workspace root folder (if exists). ",
"configuration.maven.executable.options":"Specifies default options for all mvn commands.",
"configuration.maven.terminal.useJavaHome":"If this value is true, and if the setting java.home has a value, then the environment variable JAVA_HOME will be set to the value of java.home when a new terminal window is created.",
"configuration.maven.terminal.customEnv":"Specifies an array of environment variable names and values. These environment variable values will be added to the terminal session before Maven is first executed.",
"configuration.maven.terminal.customEnv.environmentVariable":"Name of the environment variable to set.",
"configuration.maven.terminal.customEnv.value":"Value of the environment variable to set.",
"configuration.maven.completion.enabled":"Specifies whether to enable completion for POM files."
"configuration.maven.executable.preferMavenWrapper": "Specifies whether you prefer to use Maven wrapper. If true, it tries using 'mvnw' in root folder by default if the file econfiguration.xists. Otherwise it tries 'mvn' in PATH instead.",
"configuration.maven.executable.path": "Specifies absolute path of your mvn executable. When this value is empty, it tries using 'mvn' or 'mvnw' according to value of 'maven.executeble.preferMavenWapper'. Note that a relative path is not suggested, but if you do specify one, the absolute path will be resolved from your workspace root folder (if exists). ",
"configuration.maven.executable.options": "Specifies default options for all mvn commands.",
"configuration.maven.terminal.useJavaHome": "If this value is true, and if the setting java.home has a value, then the environment variable JAVA_HOME will be set to the value of java.home when a new terminal window is created.",
"configuration.maven.terminal.customEnv": "Specifies an array of environment variable names and values. These environment variable values will be added to the terminal session before Maven is first executed.",
"configuration.maven.terminal.customEnv.environmentVariable": "Name of the environment variable to set.",
"configuration.maven.terminal.customEnv.value": "Value of the environment variable to set.",
"configuration.maven.completion.enabled": "Specifies whether to enable completion for POM files.",
"configuration.maven.view": "Specifies the way of viewing Maven projects."
}

Просмотреть файл

@ -9,15 +9,17 @@
"contributes.commands.maven.history": "历史…",
"contributes.commands.maven.goal.execute": "执行命令",
"contributes.commands.maven.plugin.execute": "执行",
"contributes.commands.maven.view.hierarchical": "切换到分层视图",
"contributes.commands.maven.view.flat": "切换到扁平视图",
"contributes.views.explorer.mavenProjects": "Maven 项目",
"configuration.maven.excludedFolders": "指定搜索 Maven 项目时要排除的文件夹。",
"configuration.maven.executable.preferMavenWrapper":"指定是否优先使用 Maven Wrapper。如果为 true则尝试使用根文件夹下的 mvnw 作为可执行文件;否则尝试使用系统 PATH 中的 mvn。",
"configuration.maven.executable.path":"指定mvn可执行文件的绝对路径。当此值为空时它会根据 maven.executeble.preferMavenWapper 的值尝试使用 mvn 或 mvnw 。请注意,不建议使用相对路径,但如果指定了相对路径,则将从工作区根文件夹(如果存在)中解析绝对路径。",
"configuration.maven.executable.options":"指定所有mvn命令的默认选项。",
"configuration.maven.terminal.useJavaHome":"如果此值为 true ,并且配置项 java.home 具有值,则在创建新的终端窗口时,将环境变量 JAVA_HOME 设置为 java.home 的值。",
"configuration.maven.terminal.customEnv":"自定义环境变量。在首次执行 Maven 之前,这些环境变量值将被添加到终端会话中。",
"configuration.maven.terminal.customEnv.environmentVariable":"要设置的环境变量的名称。",
"configuration.maven.terminal.customEnv.value":"要设置的环境变量的值。",
"configuration.maven.completion.enabled":"指定是否要为 POM 文件启用补全功能。"
"configuration.maven.executable.preferMavenWrapper": "指定是否优先使用 Maven Wrapper。如果为 true则尝试使用根文件夹下的 mvnw 作为可执行文件;否则尝试使用系统 PATH 中的 mvn。",
"configuration.maven.executable.path": "指定mvn可执行文件的绝对路径。当此值为空时它会根据 maven.executeble.preferMavenWapper 的值尝试使用 mvn 或 mvnw 。请注意,不建议使用相对路径,但如果指定了相对路径,则将从工作区根文件夹(如果存在)中解析绝对路径。",
"configuration.maven.executable.options": "指定所有mvn命令的默认选项。",
"configuration.maven.terminal.useJavaHome": "如果此值为 true ,并且配置项 java.home 具有值,则在创建新的终端窗口时,将环境变量 JAVA_HOME 设置为 java.home 的值。",
"configuration.maven.terminal.customEnv": "自定义环境变量。在首次执行 Maven 之前,这些环境变量值将被添加到终端会话中。",
"configuration.maven.terminal.customEnv.environmentVariable": "要设置的环境变量的名称。",
"configuration.maven.terminal.customEnv.value": "要设置的环境变量的值。",
"configuration.maven.completion.enabled": "指定是否要为 POM 文件启用补全功能。",
"configuration.maven.view": "指定 Maven 项目的视图方式。"
}

Просмотреть файл

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
<style type="text/css">
.st0{fill:#2D2D30;}
.st1{fill:#C5C5C5;}
</style>
<g id="_x7B__PAGE_GRID__x7D_">
</g>
<g id="outline">
<path class="st0" d="M1,1h5v1h10v3H6v2h10v3H6v2h10v3H6v1H1V1z"/>
</g>
<g id="icon_x5F_bg">
<g>
<path class="st1" d="M2,2v3h3V2H2z M4,4H3V3h1V4z"/>
</g>
<g>
<path class="st1" d="M2,7v3h3V7H2z M4,9H3V8h1V9z"/>
</g>
<g>
<path class="st1" d="M2,12v3h3v-3H2z M4,14H3v-1h1V14z"/>
</g>
<rect x="6" y="3" class="st1" width="9" height="1"/>
<rect x="6" y="8" class="st1" width="9" height="1"/>
<rect x="6" y="13" class="st1" width="9" height="1"/>
</g>
<g id="icon_x5F_fg">
<path class="st0" d="M3,3v1h1V3H3z"/>
<path class="st0" d="M3,8v1h1V8H3z"/>
<path class="st0" d="M3,13v1h1v-1H3z"/>
</g>
<g id="not_x5F_bg">
</g>
<g id="not_x5F_fg">
</g>
</svg>

После

Ширина:  |  Высота:  |  Размер: 1.1 KiB

Просмотреть файл

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
<style type="text/css">
.st0{fill:#2D2D30;}
.st1{fill:#C5C5C5;}
</style>
<g id="_x7B__PAGE_GRID__x7D_">
</g>
<g id="outline">
<path class="st0" d="M2,6H1V1h5v1h10v3H6v1h4v1h6v3h-6v2h6v3h-6v1H5v-1H2V6z"/>
</g>
<g id="icon_x5F_bg">
<path class="st1" d="M9,10V7H6v1H4V5h1V2H2v3h1v9h3v1h3v-3H6v1H4V9h2v1H9z M7,8h1v1H7V8z M3,3h1v1H3V3z M7,13h1v1H7V13z"/>
<rect x="6" y="3" class="st1" width="9" height="1"/>
<rect x="10" y="8" class="st1" width="5" height="1"/>
<rect x="10" y="13" class="st1" width="5" height="1"/>
</g>
<g id="icon_x5F_fg">
<path class="st0" d="M7,13v1h1v-1H7z M7,8v1h1V8H7z M3,3v1h1V3H3z"/>
</g>
<g id="not_x5F_bg">
</g>
<g id="not_x5F_fg">
</g>
</svg>

После

Ширина:  |  Высота:  |  Размер: 1022 B

Просмотреть файл

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
<style type="text/css">
.st0{fill:#F6F6F6;}
.st1{fill:#424242;}
.st2{fill:#F0EFF1;}
</style>
<g id="_x7B__PAGE_GRID__x7D_">
</g>
<g id="outline">
<path class="st0" d="M1,1h5v1l10,0v3L6,5v2h10v3H6v2l10,0v3L6,15v1H1V1z"/>
</g>
<g id="icon_x5F_bg">
<g>
<path class="st1" d="M2,2v3h3V2H2z M4,4H3V3h1V4z"/>
</g>
<g>
<path class="st1" d="M2,7v3h3V7H2z M4,9H3V8h1V9z"/>
</g>
<g>
<path class="st1" d="M2,12v3h3v-3H2z M4,14H3v-1h1V14z"/>
</g>
<rect x="6" y="3" class="st1" width="9" height="1"/>
<rect x="6" y="8" class="st1" width="9" height="1"/>
<rect x="6" y="13" class="st1" width="9" height="1"/>
</g>
<g id="icon_x5F_fg">
<path class="st2" d="M3,3v1h1V3H3z"/>
<path class="st2" d="M3,8v1h1V8H3z"/>
<path class="st2" d="M3,13v1h1v-1H3z"/>
</g>
<g id="not_x5F_bg">
</g>
<g id="not_x5F_fg">
</g>
</svg>

После

Ширина:  |  Высота:  |  Размер: 1.1 KiB

Просмотреть файл

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
<style type="text/css">
.st0{fill:#F6F6F6;}
.st1{fill:#424242;}
.st2{fill:#F0EFF1;}
</style>
<g id="_x7B__PAGE_GRID__x7D_">
</g>
<g id="outline">
<path class="st0" d="M2,6H1V1h5v1h10v3H6v1h4v1h6v3h-6v2h6v3h-6v1H5v-1H2V6z"/>
</g>
<g id="icon_x5F_bg">
<path class="st1" d="M9,10V7H6v1H4V5h1V2H2v3h1v9h3v1h3v-3H6v1H4V9h2v1H9z M7,8h1v1H7V8z M3,3h1v1H3V3z M7,13h1v1H7V13z"/>
<rect x="6" y="3" class="st1" width="9" height="1"/>
<rect x="10" y="8" class="st1" width="5" height="1"/>
<rect x="10" y="13" class="st1" width="5" height="1"/>
</g>
<g id="icon_x5F_fg">
<path class="st2" d="M7,13v1h1v-1H7z M7,8v1h1V8H7z M3,3v1h1V3H3z"/>
</g>
<g id="not_x5F_bg">
</g>
<g id="not_x5F_fg">
</g>
</svg>

После

Ширина:  |  Высота:  |  Размер: 1.0 KiB

Просмотреть файл

@ -4,6 +4,22 @@
import { Uri, workspace } from "vscode";
export namespace Settings {
export function excludedFolders(resource: Uri): string[] {
return _getMavenSection("excludedFolders", resource);
}
export function viewType(resource: Uri): string {
return _getMavenSection("view", resource);
}
export function changeToFlatView(): void {
workspace.getConfiguration().update("maven.view", "flat", false);
}
export function changeToHierarchicalView(): void {
workspace.getConfiguration().update("maven.view", "hierarchical", false);
}
export namespace External {
export function javaHome(): string {
return workspace.getConfiguration("java").get<string>("home");
@ -14,10 +30,6 @@ export namespace Settings {
}
}
export function excludedFolders(resource: Uri): string[] {
return _getMavenSection("excludedFolders", resource);
}
export namespace Terminal {
export function useJavaHome(): boolean {
return _getMavenSection("terminal.useJavaHome");

Просмотреть файл

@ -7,16 +7,22 @@ import { ITreeItem } from "./model/ITreeItem";
import { MavenProject } from "./model/MavenProject";
import { WorkspaceFolder } from "./model/WorkspaceFolder";
enum ViewType {
HIERARCHICAL,
FLAT
}
class MavenExplorerProvider implements TreeDataProvider<ITreeItem> {
public readonly onDidChangeTreeData: vscode.Event<ITreeItem>;
private _onDidChangeTreeData: vscode.EventEmitter<ITreeItem>;
public viewType: ViewType;
private _onDidChangeTreeData: vscode.EventEmitter<ITreeItem>;
private _projectMap: Map<string, MavenProject> = new Map();
constructor() {
this._onDidChangeTreeData = new vscode.EventEmitter<ITreeItem>();
this.onDidChangeTreeData = this._onDidChangeTreeData.event;
this.viewType = ViewType.HIERARCHICAL;
this.refresh();
}

Просмотреть файл

@ -4,6 +4,7 @@
import * as _ from "lodash";
import * as path from "path";
import * as vscode from "vscode";
import { Settings } from "../../Settings";
import { Utils } from "../../Utils";
import { mavenExplorerProvider } from "../mavenExplorerProvider";
import { ITreeItem } from "./ITreeItem";
@ -13,7 +14,7 @@ import { PluginsMenu } from "./PluginsMenu";
const CONTEXT_VALUE: string = "MavenProject";
export class MavenProject implements ITreeItem {
public parent?: MavenProject;
private _rawEffectivePom: string;
private _effectivePom: any;
private _pom: any;
@ -86,6 +87,9 @@ export class MavenProject implements ITreeItem {
public getChildren(): vscode.ProviderResult<ITreeItem[]> {
const ret: ITreeItem[] = [];
ret.push(new PluginsMenu(this));
if (this.moduleNames.length > 0 && Settings.viewType(vscode.Uri.file(this._pomPath)) === "hierarchical" ) {
ret.push(...this.modules.map(m => mavenExplorerProvider.getMavenProject(m)));
}
return ret;
}

Просмотреть файл

@ -3,6 +3,7 @@
import * as vscode from "vscode";
import { TreeItemCollapsibleState } from "vscode";
import { Settings } from "../../Settings";
import { Utils } from "../../Utils";
import { mavenExplorerProvider } from "../mavenExplorerProvider";
import { ITreeItem } from "./ITreeItem";
@ -22,31 +23,47 @@ export class WorkspaceFolder implements ITreeItem {
}
public async getChildren(): Promise<ITreeItem[]> {
const children: MavenProject[] = [];
for (const pomPath of await Utils.getAllPomPaths(this._workspaceFolder)) {
const projectNode: MavenProject = mavenExplorerProvider.getMavenProject(pomPath) || new MavenProject(pomPath);
children.push(projectNode);
const newProjects: MavenProject[] = [];
const pomPaths: string[] = await Utils.getAllPomPaths(this._workspaceFolder);
for (const pomPath of pomPaths) {
if (!mavenExplorerProvider.getMavenProject(pomPath)) {
newProjects.push(new MavenProject(pomPath));
}
}
if (children.length === 0) {
await Promise.all(newProjects.map(elem => elem.parsePom()));
mavenExplorerProvider.updateProjects(...newProjects);
newProjects.forEach(p => {
p.modules.forEach(m => {
const moduleNode: MavenProject = mavenExplorerProvider.getMavenProject(m);
if (moduleNode) {
moduleNode.parent = p;
}
});
});
const allProjectNodes: MavenProject[] = mavenExplorerProvider.mavenProjectNodes;
if (allProjectNodes.length === 0) {
return [{
getTreeItem: () => new vscode.TreeItem("No Maven project found."),
getContextValue: () => "EmptyNode"
}];
}
mavenExplorerProvider.updateProjects(...children);
await Promise.all(children.map(elem => elem.parsePom()));
this.sortByName(children);
return children;
switch (Settings.viewType(this._workspaceFolder.uri)) {
case "hierarchical":
return this.sortByName(allProjectNodes.filter(m => !m.parent));
case "flat":
return this.sortByName(allProjectNodes);
default: return null;
}
}
public getTreeItem(): vscode.TreeItem | Thenable<vscode.TreeItem> {
return new vscode.TreeItem(this._workspaceFolder.name, TreeItemCollapsibleState.Expanded);
}
private sortByName(arr: MavenProject[]): void {
arr.sort((a, b) => {
private sortByName(arr: MavenProject[]): MavenProject[] {
return arr.sort((a, b) => {
return a.name > b.name ? 1 : a.name < b.name ? -1 : 0;
});
}

Просмотреть файл

@ -116,6 +116,8 @@ async function doActivate(_operationId: string, context: vscode.ExtensionContext
Utils.executeInTerminal(node.name, node.plugin.project.pomPath);
}
});
registerCommand(context, "maven.view.flat", () => Settings.changeToFlatView());
registerCommand(context, "maven.view.hierarchical", () => Settings.changeToHierarchicalView());
context.subscriptions.push(
vscode.window.onDidCloseTerminal((closedTerminal: vscode.Terminal) => {
mavenTerminal.onDidCloseTerminal(closedTerminal);
@ -123,20 +125,19 @@ async function doActivate(_operationId: string, context: vscode.ExtensionContext
// configuration change listener
vscode.workspace.onDidChangeConfiguration((e: vscode.ConfigurationChangeEvent) => {
// close all terminals with outdated JAVA related Envs
if (e.affectsConfiguration("maven.terminal.useJavaHome") || e.affectsConfiguration("maven.terminal.customEnv")) {
if (e.affectsConfiguration("maven.terminal.useJavaHome")
|| e.affectsConfiguration("maven.terminal.customEnv")
|| Settings.Terminal.useJavaHome() && e.affectsConfiguration("java.home")
) {
mavenTerminal.closeAllTerminals();
} else {
const useJavaHome: boolean = Settings.Terminal.useJavaHome();
if (useJavaHome && e.affectsConfiguration("java.home")) {
mavenTerminal.closeAllTerminals();
}
} else if (e.affectsConfiguration("maven.view")) {
mavenExplorerProvider.refresh();
}
}),
// workspace folder change listener
vscode.workspace.onDidChangeWorkspaceFolders((_e: vscode.WorkspaceFoldersChangeEvent) => {
mavenExplorerProvider.refresh();
})
);
// completion item provider
if (vscode.workspace.getConfiguration("maven", null).get<boolean>("completion.enabled")) {