idea 自定义插件 工具面板
文章目录
前言
工具窗口是IDE的子窗口,用于显示信息。这些窗口通常在主窗口的外边缘具有自己的工具栏(称为工具窗口栏),其中包含一个或多个工具窗口按钮,这些按钮可激活在主IDE窗口的左侧,底部和右侧显示的面板。
通过工具窗口可以访问有用的开发任务:查看项目结构,运行和调试应用程序,与版本控制系统和其他外部工具集成,代码分析,搜索和导航等。默认情况下,工具窗口连接到主窗口的底部和侧面。但是,您可以重新排列甚至分离它们以用作单独的窗口,例如,在另一台显示器上。
每一侧都包含两个工具窗口组,主要的和次要的,每个组中一次只能激活一个工具窗口。
下面的屏幕截图显示了几个常用的工具窗口,它们在编辑器周围占据着空间:
一、临时与永久窗口
在插件中使用工具窗口的主要场景有两种。在第一种情况下(例如,由Ant和Commander插件使用),工具窗口按钮始终可见,用户可以随时激活它并与插件功能进行交互。在第二种情况下(例如,由“Analyze Dependencies” action 使用),将创建工具窗口以显示特定操作的结果,并且用户可以在操作完成后将其关闭。
在第一种情况下,plugin.xml使用com.intellij.toolWindow在extension注册了工具窗口。扩展点属性指定显示工具窗口按钮所需的所有数据:
- 工具窗口的id(对应于工具窗口按钮上显示的文本)
- 定位,表示显示工具窗口的屏幕一侧(“左”、“右”或“下”)
- 辅助属性,指定工具窗口是显示在主组还是次组中
- 显示在工具窗口按钮上的图标(13x13像素)
除此之外,请指定工厂类 -实现该类的名称ToolWindowFactory接口。当用户单击工具窗口按钮时,将createToolWindowContent()调用工厂类的方法,并初始化工具窗口的UI。此过程可确保未使用的工具窗口不会在启动时间或内存使用上造成任何开销:如果用户不与插件的工具窗口进行交互,则不会加载或执行任何插件代码。
如果不需要为所有项目显示插件的工具窗口:
- 对于版本2020.1和更高版本,需要实现该isApplicable(Project)方法。
- 对于版本2019.3和更早版本,还请指定元素的conditionClass属性:实现的类的FQNCondition,该类可以与工具窗口工厂实现相同。
第二种情况涉及简单地调用 ToolWindowManager.registerToolWindow()从插件代码。该方法具有多个重载,可以根据任务使用。当使用带组件的重载时,组件将成为工具窗口中显示的第一个内容(选项卡)。
工具窗口可以包含多个选项卡或内容。要管理工具窗口的内容,请调用ToolWindow.getContentManager()。要添加标签页(内容),请先通过调用ContentManager.getFactory().createContent(),然后使用将其添加到工具窗口 ContentManager.addContent()。
插件可以控制是否允许用户全局或按选项卡关闭选项卡。前者是通过将canCloseContents参数传递给registerToolWindow()函数或在中指定来canCloseContents="true"完成的plugin.xml。默认值为false; 除非明确设置,否则setClosable(true)对ContentManager内容的调用将被忽略canCloseContents。如果通常启用了关闭标签页,则插件可以通过调用来禁用特定标签页的关闭Content.setCloseable(false)。
二、如何创建工具窗口?
IntelliJ平台提供了创建和配置自定义工具窗口的com.intellij.toolWindow 扩展点。此扩展点使用ToolWindowEP bean 类。
1.实现步骤
在插件项目中,创建一个实现ToolWindowFactory的类。在此类中,重写createToolWindowContent方法。在此类中,重写createToolWindowContent方法。指定此工具的内容。
配置xml, 新增 <extensions defaultExtensionNs=“com.intellij”>…</extensions>,在这个配置中 添加元素,对于这个元素,设置ToolWindowEP bean类中声明的一些属性:
- id(必需):指定工具窗口标题。
- anchor 定位(必需):指定将在其中显示“工具窗口”按钮的工具窗口栏。可能值:“left”、“right”或“bottom”
- secondary 辅助(可选):为true时,工具窗口按钮将显示在工具窗口栏的下部。默认值为false。
- factoryClass(必需):指定实现ToolWindowFactory接口的类(请参见步骤1)。
- icon 图标(可选):指定标识工具窗口的图标的路径(如果有)。
- conditionClass(可选):指定实现Condition的类。使用这个类,定义要满足的条件来显示工具窗口按钮。返回false时,工具窗口按钮不显示在工具窗口栏上。
代码如下(示例):
<extensions defaultExtensionNs="com.intellij">
<!-- Add your extensions here -->
<toolWindow id="MyToolWindowFactory" anchor="right" factoryClass="com.hunt.bar.MyToolWindowFactory"/>
</extensions>
2.实战 - 时间插件
这个插件创建了一个显示系统日期、时间和时区的示例日历工具窗口。
2.1 创建 window视图窗口
决定使用idea 的gui form来创建lable,没有了解过的小伙伴可以先了解下 IntelliJ IDE 开发Java GUI 入门
代码如下(示例):
import com.intellij.openapi.wm.ToolWindow;
import javax.swing.*;
import java.util.Calendar;
public class MyToolWindow {
private JButton refreshToolWindowButton;
private JButton hideToolWindowButton;
private JLabel currentDate;
private JLabel currentTime;
private JLabel timeZone;
private JPanel myToolWindowContent;
public MyToolWindow(ToolWindow toolWindow) {
// 绑定隐藏按钮事件
hideToolWindowButton.addActionListener(e -> toolWindow.hide(null));
// 绑定刷新按钮事件
refreshToolWindowButton.addActionListener(e -> currentDateTime());
this.currentDateTime();
}
public void currentDateTime() {
// Get current date and time
Calendar instance = Calendar.getInstance();
currentDate.setText(
instance.get(Calendar.DAY_OF_MONTH) + "/"
+ (instance.get(Calendar.MONTH) + 1) + "/"
+ instance.get(Calendar.YEAR)
);
// currentDate.setIcon(new ImageIcon(getClass().getResource("/toolWindow/Calendar-icon.png")));
int min = instance.get(Calendar.MINUTE);
String strMin = min < 10 ? "0" + min : String.valueOf(min);
currentTime.setText(instance.get(Calendar.HOUR_OF_DAY) + ":" + strMin);
// currentTime.setIcon(new ImageIcon(getClass().getResource("/toolWindow/Time-icon.png")));
// Get time zone
long gmt_Offset = instance.get(Calendar.ZONE_OFFSET); // offset from GMT in milliseconds
String str_gmt_Offset = String.valueOf(gmt_Offset / 3600000);
str_gmt_Offset = (gmt_Offset > 0) ? "GMT + " + str_gmt_Offset : "GMT - " + str_gmt_Offset;
timeZone.setText(str_gmt_Offset);
// timeZone.setIcon(new ImageIcon(getClass().getResource("/toolWindow/Time-zone-icon.png")));
}
public JPanel getContent() {
return myToolWindowContent;
}
}
对应的 .form文件如下
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.hunt.bar.MyToolWindow">
<grid id="27dc6" binding="myToolWindowContent" layout-manager="GridLayoutManager" row-count="2" column-count="5" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="277" height="400"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="9aa3f" class="javax.swing.JLabel" binding="currentDate">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Date"/>
</properties>
</component>
<component id="44be3" class="javax.swing.JLabel" binding="timeZone">
<constraints>
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="TimeZone"/>
</properties>
</component>
<component id="f02af" class="javax.swing.JLabel" binding="currentTime">
<constraints>
<grid row="0" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Time"/>
</properties>
</component>
<component id="5fceb" class="javax.swing.JButton" binding="refreshToolWindowButton">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Refresh"/>
</properties>
</component>
<component id="3edc1" class="javax.swing.JButton" binding="hideToolWindowButton">
<constraints>
<grid row="1" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Hide"/>
</properties>
</component>
<hspacer id="8bf9c">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</hspacer>
<hspacer id="26841">
<constraints>
<grid row="1" column="4" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</hspacer>
</children>
</grid>
</form>
2.2 实现 ToolWindowFactory 初始化组件
import com.intellij.openapi.project.Project;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowFactory;
import com.intellij.ui.content.Content;
import com.intellij.ui.content.ContentFactory;
import org.jetbrains.annotations.NotNull;
public class MyToolWindowFactory implements ToolWindowFactory {
@Override
public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
// 初始化自定义组件对象
MyToolWindow myToolWindow = new MyToolWindow(toolWindow);
// 组件添加到idea中
ContentFactory contentFactory = ContentFactory.SERVICE.getInstance();
Content content = contentFactory.createContent(myToolWindow.getContent(), "", false);
toolWindow.getContentManager().addContent(content);
}
}
2.3 配置xml
<extensions defaultExtensionNs="com.intellij">
<!-- Add your extensions here -->
<toolWindow id="MyToolWindowFactory" secondary="true" anchor="right" factoryClass="com.hunt.bar.MyToolWindowFactory"/>
</extensions>