在idea中可以通过扩展Configurable来设计project和application级别的设置。再结合 Persistence Model就可实现插件设置的保存。设置可以保存到单独的文件中也可和系统设置保存在一起。
一、plugin.xml配置说明
1、<applicationConfigurable>
可参考示例:ConsoleConfigurable
<extensions defaultExtensionNs="com.intellij">
<applicationConfigurable
parentId="tools"
instance="com.example.ApplicationSettingsConfigurable"
id="com.example.ApplicationSettingsConfigurable"
displayName="My Application Settings"/>
</extensions>
2、<projectConfigurable>
可参考示例:AutoImportOptionsConfigurable
<extensions defaultExtensionNs="com.intellij">
<projectConfigurable
parentId="tools"
instance="com.example.ProjectSettingsConfigurable"
id="com.example.ProjectSettingsConfigurable"
displayName="My Project Settings"
nonDefaultProject="true"/>
</extensions>
3、配置属性说明
属性 | 提供者 | 说明 |
instance | Configurable | 自定义实现类,提供了一个带有 Swing 形式的命名可配置组件,可参考示例SearchableConfigurable |
provider | ConfigurableProvider | 自定义实现类,可以有条件的显示或隐藏此配置组件Swing |
nonDefaultProject | Configurable | 仅适用于
|
displayName | Configurable ConfigurableProvider | 显示文案,如里需要国际化可用key来代替 |
| Configurable ConfigurableProvider | 国际化相关 |
id | Configurable ConfigurableProvider | 此实现的唯一 FQN 标识符 |
parentId | Configurable ConfigurableProvider | 创建设置的层次结构 |
groupWeight | Configurable ConfigurableProvider | 指定该组件在父可配置组件组中的权重(堆叠顺序)。默认权重为 0,表示顺序最低 |
dynamic | Configurable.Composite | 该组件的子组件是通过调用该 |
childrenEPName | Configurable | 指定将用于计算此组件的子项的扩展点的 FQN 名称 |
【注意】:上述属性中:1、displayName和key二选一;2、parentId和groupId二选一,且可以都不填写;
parentId属性
- 默认:当parentId和groupId都不设置时默认会放置在other组中;
- 可选:appearance、build、build.tools、editor、language、tools
二、EextendsPoint
1、Configurable
com.intellij.openapi.options.Configurable
几个重要的方法:
- 打开配置窗口时,会先调用Configurable.reset(),然后立即调用createComponent()方法,要加载显示的信息可查看ShowSettingsUtil类的实现;
- 初始化时,使用applicationConfigurable声明的应用程序设置实现必须具有不带参数的默认构造函数,使用projectConfigurableEP声明的项目设置实现必须声明一个构造函数,该构造函数具有一个类型的参数
- 点击设置对话框的取消或确定按钮会清空一次资源,系统会调用disposeUIResources()方法,结束当前生命周期。
全局设置标记:
Configurable.NoScroll
- - 通知设置对话框不要向表单添加滚动条。
Configurable.NoMargin
- - 通知设置对话框不要向表单添加空边框。
Configurable.Beta
- (2022.3) -在设置树中的设置页面标题旁边添加Beta标签。
com.intellij.openapi.options.ConfigurableEP
专门用于特定类型设置的类,比如向Settings | Editor | General | Appearance 中添加一个额外的设置就可以使用扩展com.intellij.editorSmartKeysConfigurable,实现类可通过继承EditorSmartKeysConfigurableEP类来实现
2、ConfigurableProvider
Configurable
IntelliJ 调用ConfigurableProvider.canCreateConfigurable()
,它评估运行时条件以确定设置更改在当前上下文中是否有意义。如果显示设置有意义,can方法则返回true
。然后平台才会调用ConfigurableProvider.createConfigurable()
返回Configurable
设置实现的对象。
可参考示例RunToolbarSettingsConfigurableProvider
三、自定义设置组
虽然我们可以指定parentId,但如果插件比较复杂就可能需要实现层级式的设置页了。
单独的EP的父子设置
注意第二个配置的parentId值它设置的是第一个配置的id值。
<extensions defaultExtensionNs="com.intellij">
<projectConfigurable
parentId="tools"
id="com.intellij.sdk.tasks"
displayName="Tasks"
nonDefaultProject="true"
instance="com.intellij.sdk.TaskConfigurable"/>
<projectConfigurable
parentId="com.intellij.sdk.tasks"
id="com.intellij.sdk.tasks.servers"
displayName="Servers"
nonDefaultProject="true"
instance="com.intellij.sdk.TaskRepositoriesConfigurable"/>
</extensions>
嵌套 EP 的父子设置
这种设置是基于id值的,比如下例中com.intellij.sdk.tasks和com.intellij.sdk.tasks.servers。这里的子必须前缀为com.intellij.sdk.tasks,然后再加.children。
<extensions defaultExtensionNs="com.intellij">
<projectConfigurable
parentId="tools"
id="com.intellij.sdk.tasks"
displayName="Tasks"
nonDefaultProject="true"
instance="com.intellij.sdk.TaskConfigurable"/>
<configurable
id="com.intellij.sdk.tasks.servers"
displayName="Servers"
nonDefaultProject="true"
instance="com.intellij.sdk.TaskRepositoriesConfigurable"/>
</projectConfigurable>
</extensions>
四、示例程序
1、定义State
定义AppSettingsState类
@State(
name = "org.intellij.sdk.settings.AppSettingsState",
storages = @Storage("SdkSettingsPlugin.xml")
)
public class AppSettingsState implements PersistentStateComponent<AppSettingsState> {
public String userId = "John Q. Public";
public boolean ideaStatus = false;
public static AppSettingsState getInstance() {
return ApplicationManager.getApplication().getService(AppSettingsState.class);
}
@Nullable
@Override
public AppSettingsState getState() {
return this;
}
@Override
public void loadState(@NotNull AppSettingsState state) {
XmlSerializerUtil.copyBean(state, this);
}
}
- name: 指定的是实现类的全路径;
- storages:默认路径为~/Library/Application Support/JetBrains/IntelliJIdea2023.1/plugins;测试时此文件位于code_samples /settings /build /idea-sandbox /config /options/中;
- AppSettingsState:中定义的属性默认为持久化的;如果不需要持久化可用@com.intellij.util.xmlb.annotations.Transient来标注不再持久化;
这个配置不建议使用,因为idea要废弃对component的使用,在java类中通过注解的方式来实现
<application>
<component name="org.intellij.sdk.settings.AppSettingsState">
<option name="ideaStatus" value="true" />
</component>
</application>
2、定义UI
public class AppSettingsComponent {
private final JPanel myMainPanel;
private final JBTextField myUserNameText = new JBTextField();
private final JBCheckBox myIdeaUserStatus = new JBCheckBox("Do you use IntelliJ IDEA? ");
public AppSettingsComponent() {
myMainPanel = FormBuilder.createFormBuilder()
.addLabeledComponent(new JBLabel("Enter user name: "), myUserNameText, 1, false)
.addComponent(myIdeaUserStatus, 1)
.addComponentFillVertically(new JPanel(), 0)
.getPanel();
}
public JPanel getPanel() {
return myMainPanel;
}
public JComponent getPreferredFocusedComponent() {
return myUserNameText;
}
@NotNull
public String getUserNameText() {
return myUserNameText.getText();
}
public void setUserNameText(@NotNull String newText) {
myUserNameText.setText(newText);
}
public boolean getIdeaUserStatus() {
return myIdeaUserStatus.isSelected();
}
public void setIdeaUserStatus(boolean newStatus) {
myIdeaUserStatus.setSelected(newStatus);
}
}
3、定义AppSettingsConfigurable类
public class AppSettingsConfigurable implements Configurable {
private AppSettingsComponent mySettingsComponent;
// A default constructor with no arguments is required because this implementation
// is registered as an applicationConfigurable EP
@Nls(capitalization = Nls.Capitalization.Title)
@Override
public String getDisplayName() {
return "SDK: Application Settings Example";
}
@Override
public JComponent getPreferredFocusedComponent() {
return mySettingsComponent.getPreferredFocusedComponent();
}
@Nullable
@Override
public JComponent createComponent() {
mySettingsComponent = new AppSettingsComponent();
return mySettingsComponent.getPanel();
}
@Override
public boolean isModified() {
AppSettingsState settings = AppSettingsState.getInstance();
boolean modified = !mySettingsComponent.getUserNameText().equals(settings.userId);
modified |= mySettingsComponent.getIdeaUserStatus() != settings.ideaStatus;
return modified;
}
@Override
public void apply() {
AppSettingsState settings = AppSettingsState.getInstance();
settings.userId = mySettingsComponent.getUserNameText();
settings.ideaStatus = mySettingsComponent.getIdeaUserStatus();
}
@Override
public void reset() {
AppSettingsState settings = AppSettingsState.getInstance();
mySettingsComponent.setUserNameText(settings.userId);
mySettingsComponent.setIdeaUserStatus(settings.ideaStatus);
}
@Override
public void disposeUIResources() {
mySettingsComponent = null;
}
}
配置
<extensions defaultExtensionNs="com.intellij">
<applicationConfigurable parentId="tools" instance="org.intellij.sdk.settings.AppSettingsConfigurable"
id="org.intellij.sdk.settings.AppSettingsConfigurable"
displayName="SDK: Application Settings Example"/>
<applicationService serviceImplementation="org.intellij.sdk.settings.AppSettingsState"/>
</extensions>
4、测试 runIde
SdkSettingsPlugin.xml存储位置:code_samples /settings /build /idea-sandbox /config /options/中