目录
idea插件开发资料实在太少,官方demo的例子也很少。
这里笔者介绍一下官方demo中没有的例子——底部窗口。
这只是一个demo,用于实际开发,还要结合官方手册来。
先看下效果图:
给大家看下我的目录结构:
第一步:新建一个Executor
package com.example.action.t3_tool_windows.console_view.bottom_console;
import com.example.utils.MyIconUtil;
import com.intellij.execution.Executor;
import org.jetbrains.annotations.NotNull;
import javax.swing.Icon;
public class ConsoleTool_Executor extends Executor {
public static final String PLUGIN_ID = "SQL Plugin ID";
public static final String TOOL_WINDOW_ID = "SQL Scanner";
public static final String CONTEXT_ACTION_ID = "custom context action id";
@NotNull
@Override
public String getId() {
return PLUGIN_ID;
}
@Override
public String getToolWindowId() {
return TOOL_WINDOW_ID;
}
@Override
public Icon getToolWindowIcon() {
return MyIconUtil.ICON;
}
@NotNull
@Override
public Icon getIcon() {
return MyIconUtil.ICON;
}
@Override
public Icon getDisabledIcon() {
return MyIconUtil.ICON;
}
@Override
public String getDescription() {
return TOOL_WINDOW_ID;
}
@NotNull
@Override
public String getActionName() {
return TOOL_WINDOW_ID;
}
@NotNull
@Override
public String getStartActionText() {
return TOOL_WINDOW_ID;
}
@Override
public String getContextActionId() {
return CONTEXT_ACTION_ID;
}
@Override
public String getHelpId() {
return TOOL_WINDOW_ID;
}
}
在 plugin.xml 中添加, 注意路径换成你自己的。
<!-- 插件扩展 -->
<extensions defaultExtensionNs="com.intellij">
<!-- 自定义 底部view -->
<executor id="CustomRunExecutor" order="last" implementation="com.example.action.t3_tool_windows.console_view.bottom_console.ConsoleTool_Executor"/>
</extensions>
我的build.gradle配置如下:
plugins {
id 'org.jetbrains.intellij' version '0.4.10'
id "org.jetbrains.kotlin.jvm" version "1.3.41"
id 'java'
}
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
}
apply {
"java"
"terminal"
"ant"
}
group 'org.example'
version '1.0-SNAPSHOT'
// See https://github.com/JetBrains/gradle-intellij-plugin/
intellij {
version '2019.3.3'
// 必须,否则无法找到 PsiClass 等
plugins = ['java', 'gradle']
intellij.updateSinceUntilBuild false
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
apply {
"java"
"terminal"
"ant"
}
test {
useJUnitPlatform()
}
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
}
buildPlugin {
buildSearchableOptions.enabled = false
}
第二步:自定义按钮
先添加后面需要用到的工具类
这个类是为了获取当前窗口的运行状态,以便后续扩充操作。
public enum MyProjectUtil {
;
public static void setRunning(Project project, String key, boolean value) {
PropertiesComponent.getInstance(project).setValue(key, value);
}
public static boolean getRunning(Project project, String key) {
return PropertiesComponent.getInstance(project).getBoolean(key);
}
}
下面这个类是获取正在运行的Executor
public enum MyExecutorUtil {
;
/**
* 返回正在运行的 Executor
* @param id Executor id
*/
public static Executor getRunExecutorInstance(String id) {
return ExecutorRegistry.getInstance().getExecutorById(id);
}
}
重启按钮Action:
package com.example.action.t3_tool_windows.console_view.bottom_console.toolbar;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.project.DumbAware;
/**
* 重启 ConsoleTool
*/
public class ConsoleTool_Rerun_Action extends AnAction implements DumbAware {
/**
* 重启 ToolWindow
*/
private Runnable rerun;
public ConsoleTool_Rerun_Action(Runnable rerun) {
super("Rerun", "Rerun", AllIcons.Actions.Restart);
this.rerun = rerun;
}
/**
* 执行动作
*/
@Override
public void actionPerformed(AnActionEvent e) {
rerun.run();
}
/**
* 监听该Action, 每次焦点更换、窗口切换都会触发 update
*/
@Override
public void update(AnActionEvent e) {
e.getPresentation().setVisible(rerun != null);
}
}
关闭按钮Action
package com.example.action.t3_tool_windows.console_view.bottom_console.toolbar;
import com.example.utils.MyProjectUtil;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.project.DumbAware;
public class ConsoleTool_Stop_Action extends AnAction implements DumbAware {
/**
* 停止 ToolWindow
*/
private Runnable stop;
public ConsoleTool_Stop_Action(Runnable stop) {
super("Stop", "Stop", AllIcons.Actions.Suspend);
this.stop = stop;
}
/**
* 执行动作
*/
@Override
public void actionPerformed(AnActionEvent e) {
stop.run();
}
/**
* 监听该Action, 每次焦点更换、窗口切换都会触发 update
*/
@Override
public void update(AnActionEvent e) {
if (null != e && null != e.getProject()) {
e.getPresentation().setEnabled(MyProjectUtil.getRunning(e.getProject(), "running"));
}
}
}
一个自定义的执行按钮
package com.example.action.t3_tool_windows.console_view.bottom_console.toolbar;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import org.jetbrains.annotations.NotNull;
public class Scanner_Action extends AnAction {
private ConsoleView consoleView;
public Scanner_Action(ConsoleView consoleView) {
super("Scanner Sql", "Scanner sql", AllIcons.Actions.Upload);
this.consoleView = consoleView;
}
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
// Messages.showMessageDialog("SQL Scan Action", "Scanner", Messages.getInformationIcon());
if (null != consoleView) {
consoleView.print("新输出一条日志.", ConsoleViewContentType.NORMAL_OUTPUT);
}
}
}
第三步:定义runner
package com.example.action.t3_tool_windows.console_view.bottom_console;
import com.example.action.t3_tool_windows.console_view.bottom_console.toolbar.ConsoleTool_Rerun_Action;
import com.example.action.t3_tool_windows.console_view.bottom_console.toolbar.ConsoleTool_Stop_Action;
import com.example.action.t3_tool_windows.console_view.bottom_console.toolbar.Scanner_Action;
import com.example.utils.MyExecutorUtil;
import com.intellij.execution.DefaultExecutionResult;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.ExecutionManager;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.configurations.RunProfileState;
import com.intellij.execution.filters.TextConsoleBuilder;
import com.intellij.execution.filters.TextConsoleBuilderFactory;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.execution.ui.RunnerLayoutUi;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.project.Project;
import com.intellij.ui.content.Content;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
public class ConsoleTool_Runner {
/**
* Project
*/
private Project project = null;
/**
* 视图面板
*/
private ConsoleView consoleView = null;
/**
* 重启/运行 ToolWindow
*/
private Runnable rerun;
/**
* 停止 ToolWindow
*/
private Runnable stop;
public ConsoleTool_Runner(@NotNull Project project, Runnable rerun, Runnable stop) {
this.project = project;
this.consoleView = createConsoleView(project);
this.rerun = rerun;
this.stop = stop;
}
private ConsoleView createConsoleView(Project project) {
TextConsoleBuilder consoleBuilder = TextConsoleBuilderFactory.getInstance().createBuilder(project);
ConsoleView console = consoleBuilder.getConsole();
console.print("第一行日志输出", ConsoleViewContentType.LOG_DEBUG_OUTPUT);
return console;
}
public void run() {
// 返回定义的 Executor
Executor executor = MyExecutorUtil.getRunExecutorInstance(ConsoleTool_Executor.PLUGIN_ID);
if (executor == null) {
return;
}
// 创建 RunnerLayoutUi
final RunnerLayoutUi.Factory factory = RunnerLayoutUi.Factory.getInstance(project);
RunnerLayoutUi layoutUi = factory.create("id", "title", "session name", project);
// 创建 panel
final JPanel panel = new JPanel();
panel.add(consoleView.getComponent(), BorderLayout.CENTER);
// 创建描述信息
RunContentDescriptor descriptor = new RunContentDescriptor(new RunProfile() {
@Nullable
@Override
public RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment environment) throws ExecutionException {
return null;
}
@NotNull
@Override
public String getName() {
return "name";
}
@Nullable
@Override
public Icon getIcon() {
return null;
}
}, new DefaultExecutionResult(), layoutUi);
descriptor.setExecutionId(System.nanoTime());
final Content content = layoutUi.createContent("contentId", panel, "displayName", AllIcons.Debugger.Console, panel);
content.setCloseable(true);
layoutUi.addContent(content);
// 新增左边工具条
layoutUi.getOptions().setLeftToolbar(createActionToolbar(consoleView), "RunnerToolbar");
ExecutionManager.getInstance(project).getContentManager().showRunContent(executor, descriptor);
}
private ActionGroup createActionToolbar(ConsoleView consoleView) {
final DefaultActionGroup actionGroup = new DefaultActionGroup();
// ConsoleView 按钮: warp
actionGroup.add(consoleView.createConsoleActions()[2]);
// ConsoleView 按钮: scroll to end
actionGroup.add(consoleView.createConsoleActions()[3]);
// ConsoleView 按钮: clear
actionGroup.add(consoleView.createConsoleActions()[5]);
// 自定义按钮
actionGroup.add(new Scanner_Action(consoleView));
actionGroup.add(new ConsoleTool_Rerun_Action(rerun));
actionGroup.add(new ConsoleTool_Stop_Action(stop));
return actionGroup;
}
}
第四步:定义插件Action
package com.example.action.t3_tool_windows.console_view.bottom_console.action;
import com.example.action.t3_tool_windows.console_view.bottom_console.ConsoleTool_Runner;
import com.example.utils.MyProjectUtil;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
public class ConsoleTool_Action extends AnAction {
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
runExecutor(e.getProject());
}
public void runExecutor(Project project) {
if (project == null) {
return;
}
// 设置restart (再次执行这个action)
Runnable rerun = () -> runExecutor(project);
// 设置stop
Runnable stop = () -> MyProjectUtil.setRunning(project, "running", false);
MyProjectUtil.setRunning(project, "running", true);
ConsoleTool_Runner executor = new ConsoleTool_Runner(project, rerun, stop);
executor.run();
}
}
至此代码写完!
第五步:plugin.xml 配置
注意,下面的路径需要更换成你自己的路径。
<!-- 插件扩展 -->
<extensions defaultExtensionNs="com.intellij">
<!-- 自定义 底部view -->
<executor id="CustomRunExecutor" order="last" implementation="com.example.action.t3_tool_windows.console_view.bottom_console.ConsoleTool_Executor"/>
</extensions>
<actions>
<!-- 自定义分组 -->
<group id="zhang.group1.id" text="Zhang-菜单汇总" description="Group1 description">
<add-to-group group-id="MainMenu" anchor="last"/>
<action id="zhang.bottom_tool.id"
class="com.example.action.t3_tool_windows.console_view.bottom_console.action.ConsoleTool_Action"
text="底部-ToolWindow" description="Description">
</action>
</group>
</actions>
相关文章推荐
笔者的开源插件:Java Mybatis SQL Scannerhttps://zhangxiaofan.blog.csdn.net/article/details/123094358
idea plugin插件开发2——预览代码(多窗口)https://zhangxiaofan.blog.csdn.net/article/details/123097015idea plugin插件开发3——可编辑表单
https://zhangxiaofan.blog.csdn.net/article/details/123097368