idea插件开发--配置

gitee地址:https://gitee.com/jyq_18792721831/studyplugin.git
idea插件开发入门
idea插件开发–配置
idea插件开发–服务-翻译插件
idea插件开发–组件–编程久坐提醒

介绍

很多时候,我们使用插件都需要配置一些信息,只有配置了信息,插件才能更好的进行服务,增加我们的效率。
但是又不能每次使用插件都进行配置,即使我们使用对象将配置缓存下来,但是当idea重启后,又必须重新进行配置,这样的插件是没人使用的。
所以我们需要将配置进行持久化,当idea进行重启后,也能度过读取持久化的配置,再次提供服务。
idea插件提供的持久化方案有多种,这只是最简单,最基础的一种。
即使是最简单,最基础的这种,也能满足绝大多数的配置持久化需求。

存储接口

PropertiesComponent公有三个子类
在这里插入图片描述
首先PropertiesComponentImpl实现了配置的存储和读取。
然后AppPropertiesComponentImpl则是全局的,所有的idea实例只有一份相同的配置的实现,即AppPropertiesComponentImpl的作用域是对全部的idea生效。所有的idea实例,只要key相同,则值也是相同的。
ProjectPropertiesComponentImpl的作用域则是对项目进行隔离,每个idea实例都可以有相同的key,而且对应值可以不同。
具体使用哪一种作用域,则是在编码时的getInstance方法决定,getInstance方法是个重载方法,一个有参数,参数是Project,一个没有参数。
很明显,没有参数的就是全局的,作用域是App,有参数的是就是部分的,作用域是Project。

配置界面

插件的配置一般是setting的界面中配置的
在这里插入图片描述
要想自己的插件也在这里配置,就必须自己决定配置的界面,以及告诉idea,如何展示。
SearchableConfigurable接口。
实现了SearchableConfigurable接口,就会在settings下面的tools下面展示。
SearchableConfigurable定义了一些方法:

  • getId:获取id,插件内不能重复
  • getDisplayName:获取tools下面展示的名字
  • createComponent:获取展示的界面
  • isModified:是否可用,是否可配置
  • apply:配置完成后,点击了确定或者应用后执行的逻辑

实例

目标

配置一个测试的值,然后使用Action触发读取,并使用通知展示。

创建项目

一定要创建项目,因为当一个项目中存在多个模块,且多个模块都是插件的时候,就存在无法直接启动和调试的问题。
国内开发插件是有点难受,使用gradle的方式吧,依赖好管理,但是idea的sdk实在下载不下来,而且,gradler管理工具也不咋会用。
算了,还是老老实实的用最原始的方式,也是最靠谱的方式。
在这里插入图片描述
创建好后,配置plugin.xml(其实就是将helloword的plugin.xml拷贝过来,修改id和name即可,helloword见idea插件开发入门

  <extensions defaultExtensionNs="com.intellij">
    <!-- Add your extensions here -->
    <!-- displayType只有这四种类型, id 在一个插件内不能重复,isLogByDefault表示是否在 Event Log 中记录 -->
    <notificationGroup displayType="BALLOON" id="helloword.notification.balloon" isLogByDefault="false"/>
  </extensions>

  <actions>
    <!-- Add your actions here -->
    <action id="com.study.plugin.simpleconfig" class="com.study.plugin.simpleconfig.action.TestConfigAction" text="TestConfigAction"
            description="TestConfigAction">
      <add-to-group group-id="ToolsMenu" anchor="last"/>
      <keyboard-shortcut keymap="$default" first-keystroke="ctrl alt SEMICOLON"/>
    </action>
  </actions>

项目结构如图
在这里插入图片描述

工具类封装

NotificationUtil
封装三种类型的通知

import com.intellij.notification.Notification;
import com.intellij.notification.NotificationGroup;
import com.intellij.notification.NotificationGroupManager;
import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;

public class NotificationUtil {

    // 获取通知组管理器
    private static NotificationGroupManager manager = NotificationGroupManager.getInstance();

    // 获取注册的通知组
    private static NotificationGroup balloon = manager.getNotificationGroup("helloword.notification.balloon");

    public static void info(String msg) {
        Notification notification = balloon.createNotification(msg, NotificationType.INFORMATION);
        Notifications.Bus.notify(notification);
    }

    public static void warning(String msg) {
        Notification notification = balloon.createNotification(msg, NotificationType.WARNING);
        Notifications.Bus.notify(notification);
    }

    public static void error(String msg) {
        Notification notification = balloon.createNotification(msg, NotificationType.ERROR);
        Notifications.Bus.notify(notification);
    }
}

接着把插件的id,name等等的常量做个封装

public class SimpleConfigKeys {
    public static final String SETTING_ID = "com.study.plugin.simpleconfig.setting.id";
    public static final String SETTING_NAME = "简单配置测试";
    public static final String SETTING_TEST_CONFIG_KEY = "text.config";
}

还有最重要的一个,配置值的存储工具类

import com.intellij.ide.util.PropertiesComponent;

public class SimpleConfigUtil {

    private static final PropertiesComponent propertiesComponent = PropertiesComponent.getInstance();

    public static String getString(String key) {
        // key
        // key defaultValue
        return propertiesComponent.getValue(key);
    }

    public static void save(String key, Object value) {
        if (value instanceof String) {
            save(key, (String) value);
        } else if (value instanceof Integer) {
            save(key, (int) value);
        } else if (value instanceof Boolean) {
            save(key, (boolean) value);
        } else if (value instanceof Float) {
            save(key, (float) value);
        } else {
            NotificationUtil.error("type error : " + value);
        }
    }

    private static void save(String key, String value) {
        // key value
        propertiesComponent.setValue(key, value);
    }

    private static void save(String key, int value) {
        // key value defaultValue
        propertiesComponent.setValue(key, value, 0);
    }

    private static void save(String key, boolean value) {
        // key value
        // key value defaultValue
        propertiesComponent.setValue(key, value);
    }

    private static void save(String key, float value) {
        // key value defaultValue
        propertiesComponent.setValue(key, value, 0.0f);
    }

}

配置存储全局作用域即可。

setting界面

创建UI
在这里插入图片描述
增加后,会生成java类和form文件
在这里插入图片描述

界面结构如下,需要什么,可以拖动控件放到需要的位置上
在这里插入图片描述
最顶层是一个JPanel,属性名字是rootPanel
在这里插入图片描述
为了方便管理,我们增加一个二级Pannel,不需要名字,增加边框
在这里插入图片描述
选中Panel,并设置border的属性即可
二级Panel下有两个控件:JLabel,用于展示,JTextField,用于输入。
因为我们需要获取输入的值,所以需要给JTextField设置名字。
此时查看java类,是没有代码生成的,我们需要idea帮我们将form转为java代码
在这里插入图片描述
然后设置module的启动配置
在这里插入图片描述
有了启动配置后,进行编译,编译成功后,java类中就会自动生成代码
在这里插入图片描述
前面说过,我们需要获取输入框的控件,然后获取输入的值,设置动作监听等等,所以使用lombok将JTextField控件暴露出去
在这里插入图片描述
将lombok加入到classpath中(lombok在高版本的idea中自动支持)
加入后会下载相关的jar,有可能会非常慢
在这里插入图片描述
需要注意,rootJPanel也需要增加getter方法
在这里插入图片描述
虽然自动生成了getRootComponent方法,但是这个方法不是给我们编码用的
在这里插入图片描述
注释的很明白,不要在你的代码中使用这些方法
在这里插入图片描述

在java文件中,右键,自动生成测试方法
在这里插入图片描述
在这里插入图片描述
一定要给最顶层的JPanel设置属性名字,才能自动生成测试方法
在这里插入图片描述
你的UI就会展示出来
在这里插入图片描述
如果还设置了动作监听,也能进行测试的,按钮什么的,都可以进行测试。

配置界面到setting中

写好了界面,我们就需要把界面配置到setting中,也就是需要编写实现SearchableConfigurable的类了

import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.util.NlsContexts;
import com.study.plugin.simpleconfig.ui.SimpleConfigSettingUI;
import com.study.plugin.simpleconfig.util.NotificationUtil;
import com.study.plugin.simpleconfig.util.SimpleConfigKeys;
import com.study.plugin.simpleconfig.util.SimpleConfigUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.JComponent;
import javax.swing.JTextField;

public class SimpleConfigSetting implements SearchableConfigurable {

    private SimpleConfigSettingUI form = new SimpleConfigSettingUI();

    @Override
    public @NotNull
    @NonNls
    String getId() {
        return SimpleConfigKeys.SETTING_ID;
    }

    @Override
    public @NlsContexts.ConfigurableName String getDisplayName() {
        return SimpleConfigKeys.SETTING_NAME;
    }

    @Override
    public @Nullable
    JComponent createComponent() {
        return form.$$$getRootComponent$$$();
    }

    @Override
    public boolean isModified() {
        return true;
    }

    @Override
    public void apply() throws ConfigurationException {
        JTextField simpleConfigInput = form.getSimpleConfigInput();
        String inputValue = simpleConfigInput.getText();
        SimpleConfigUtil.save(SimpleConfigKeys.SETTING_TEST_CONFIG_KEY, inputValue);
        NotificationUtil.info("save " + inputValue + " success!");
    }
}

其实很简单,就是把输入框中的值,保存到持久化中。
编写完成后,需要将我们编写的类配置到idea中。
可以把整个idea想象成一个spring的项目,在spring中,是spring去管理对象实例的,在idea中,也类似差不多。在spring中有注解和xml方式注入bean,在idea中主要是在plugin.xml中将我们自己写的实例注入到idea中的。
所以需要将SearchableConfigurable接口的实现类的实例,注入到idea中

  <extensions defaultExtensionNs="com.intellij">
    <!-- Add your extensions here -->
    <!-- displayType只有这四种类型, id 在一个插件内不能重复,isLogByDefault表示是否在 Event Log 中记录 -->
    <notificationGroup displayType="BALLOON" id="simpleconfig.notification.balloon" isLogByDefault="false"/>
    <applicationConfigurable parentId="tools" instance="com.study.plugin.simpleconfig.config.SimpleConfigSetting"
                             id="com.study.plugin.simpleconfig.setting.config.id" displayName="测试配置菜单"/>
  </extensions>

可以看到我们注入的是全局的配置,如果是项目的配置,就需要使用projectConfigurable的标签了,这里面配置的类都是configurable接口的实现类。

读取配置

读取配置是在Action中的,也很简单,从持久化工具类中获取值,然后通知输出即可

import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.study.plugin.simpleconfig.util.NotificationUtil;
import com.study.plugin.simpleconfig.util.SimpleConfigKeys;
import com.study.plugin.simpleconfig.util.SimpleConfigUtil;

public class TestConfigAction extends AnAction {

    @Override
    public void actionPerformed(AnActionEvent e) {
     String configValue = SimpleConfigUtil.getString(SimpleConfigKeys.SETTING_TEST_CONFIG_KEY);
        if(StringUtil.isEmpty(configValue)) {
            NotificationUtil.error("empty");
        }
        NotificationUtil.info(configValue);
    }
}

验证

至此,整个实例就完成了,完整的项目结构如下
在这里插入图片描述
启动测试下(注意启动正确的module)
首先是setting的配置页
在这里插入图片描述
可以看到,这里配置的就是我们在plugin.xml中配置的数据生效了。
接下来是配置界面
在这里插入图片描述
也是一样的,我们试着配置
在这里插入图片描述
然后使用tools下的菜单触发
在这里插入图片描述
因为我们使用的是唯一的沙盒,所有会有helloword的插件。
在这里插入图片描述
点击,发现和预期的一样,通知里面是我们配置的值。
接下来重启idea(沙盒的)
在这里插入图片描述
可以看到,重启沙盒的idea后,原本开发的idea的调试关联就丢失了
在这里插入图片描述
在非调试的状态下,重新触发读取操作,发现还是能够读取到我们配置的值,即使我们重启过idea(沙盒)
在这里插入图片描述
这样就达到了我们的目的。

扩展

如果我想每次配置的时候,都把已有的配置放在输入框中呢?
因为现在打开配置,默认是空的,这样如果打开配置,直接点击确定,会把空值写入。
在这里插入图片描述
要实现这个小功能,也很简单,在获取配置的JPanel的之前,将配置中的值,设置到控件中即可。
在这里插入图片描述
还记得吗,我们之前配置的值是“测试1”,现在打开配置界面,看看输入框中是不是
在这里插入图片描述
预期一致。

打包

打包后会生成可安装的压缩包
在这里插入图片描述
和helloword中的不同,helloword中的是jar包,这里是zip包。
打包后生成jar包还是zip包,取决于是否有第三方依赖。
在simpleconfig中,我们有lombok的第三方依赖,在打包的时候,会把lombok的包也打进去,所以是zip包,在helloword中,没有第三方包,所以是jar包。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值