settings_guide.md: cleanup and small clarification in performance tip

This commit is contained in:
Karol Lewandowski 2022-03-15 14:37:03 +01:00
parent 3339d02e58
commit 40415caefd

View File

@ -14,60 +14,71 @@ Settings can [affect different levels](https://www.jetbrains.com/help/idea/confi
This document describes adding custom Settings at the Project and Application (or Global, IDE) levels. This document describes adding custom Settings at the Project and Application (or Global, IDE) levels.
## Extension Points for Settings ## Extension Points for Settings
Custom Settings implementations are declared in a plugin's configuration (<path>plugin.xml</path>) file using one of two Extension Points (EPs), depending on the level of the Settings.
Custom Settings implementations are declared in a plugin's configuration (<path>plugin.xml</path>) file using one of two extension points (EP), depending on the level of the Settings.
Many [attributes](#settings-declaration-attributes) are shared between the EP declarations. Many [attributes](#settings-declaration-attributes) are shared between the EP declarations.
Application and Project Settings typically provide an implementation based on the [`Configurable`](upsource:///platform/ide-core/src/com/intellij/openapi/options/Configurable.java) interface because they do not have runtime dependencies. Application and Project Settings typically provide an implementation based on the [`Configurable`](upsource:///platform/ide-core/src/com/intellij/openapi/options/Configurable.java) interface because they do not have runtime dependencies.
See [Implementations for Settings Extension Points](#implementations-for-settings-extension-points) for more information. See [Implementations for Settings Extension Points](#implementations-for-settings-extension-points) for more information.
> For performance reasons, the recommended approach is to declare as much information as possible about a Settings' implementation using attributes in the Extension Point. > For performance reasons, it is recommended to declare as much information as possible about a 'Settings' implementation using attributes in the EP element in the <path>plugin.xml</path> descriptor.
> If it is not declared, the component must be loaded to retrieve it from the implementation, degrading UI responsiveness. > If it is not declared, the component must be loaded to retrieve it from the implementation, degrading UI responsiveness.
> >
{type="note"} {type="note"}
### Declaring Application Settings ### Declaring Application Settings
Settings at the Application level use the `com.intellij.applicationConfigurable` EP.
The application-level settings are declared using `com.intellij.applicationConfigurable` EP.
An example `<applicationConfigurable>` EP declaration is shown below. An example `<applicationConfigurable>` EP declaration is shown below.
The declaration indicates the settings are a child of the `tools` settings group, the implementation FQN is `org.company.ApplicationSettingsConfigurable`, the unique ID is the same as the implementation FQN, and the (non-localized) title displayed to users is "My Application Settings". The declaration indicates the settings are a child of the `tools` settings group, the implementation FQN is `com.example.ApplicationSettingsConfigurable`, the unique ID is the same as the implementation fully qualified name (FQN), and the (non-localized) title displayed to users is "My Application Settings".
See [Settings Declaration Attributes](#settings-declaration-attributes) for more information. See [](#settings-declaration-attributes) for more information.
```xml ```xml
<extensions defaultExtensionNs="com.intellij"> <extensions defaultExtensionNs="com.intellij">
<applicationConfigurable parentId="tools" instance="org.company.ApplicationSettingsConfigurable" <applicationConfigurable parentId="tools"
id="org.company.ApplicationSettingsConfigurable" displayName="My Application Settings"/> instance="com.example.ApplicationSettingsConfigurable"
</extensions> id="com.example.ApplicationSettingsConfigurable"
displayName="My Application Settings"/>
</extensions>
``` ```
### Declaring Project Settings ### Declaring Project Settings
Project level Settings use the `com.intellij.projectConfigurable` EP.
The project-level settings are declared using `com.intellij.projectConfigurable` EP.
An example `<projectConfigurable>` EP declaration is shown below. An example `<projectConfigurable>` EP declaration is shown below.
Similar to the application setting example above, but it includes the additional attribute `nonDefaultProject` indicating these settings do not apply to the [default project](https://www.jetbrains.com/help/idea/configure-project-settings.html#new-default-settings). Similar to the application setting example above, but it includes the additional attribute `nonDefaultProject` indicating these settings do not apply to the [default project](https://www.jetbrains.com/help/idea/configure-project-settings.html#new-default-settings).
See [Settings Declaration Attributes](#settings-declaration-attributes) for details. See [](#settings-declaration-attributes) for details.
```xml ```xml
<extensions defaultExtensionNs="com.intellij"> <extensions defaultExtensionNs="com.intellij">
<projectConfigurable parentId="tools" instance="org.company.ProjectSettingsConfigurable" <projectConfigurable parentId="tools"
id="org.company.ProjectSettingsConfigurable" displayName="My Project Settings" instance="com.example.ProjectSettingsConfigurable"
nonDefaultProject="true"/> id="com.example.ProjectSettingsConfigurable"
</extensions> displayName="My Project Settings"
nonDefaultProject="true"/>
</extensions>
``` ```
### Settings Declaration Attributes ### Settings Declaration Attributes
Readers are encouraged to review the Javadoc comments for [`Configurable`](upsource:///platform/ide-core/src/com/intellij/openapi/options/Configurable.java) because the attribute information applies to `ConfigurableProvider` as well as `Configurable`, as noted. Readers are encouraged to review the Javadoc comments for [`Configurable`](upsource:///platform/ide-core/src/com/intellij/openapi/options/Configurable.java) because the attribute information applies to `ConfigurableProvider` as well as `Configurable`, as noted.
This section provides some additional clarification of those comments. This section provides some additional clarification of those comments.
#### Table of Attributes #### Table of Attributes
The attributes supported by `com.intellij.applicationConfigurable` and `com.intellij.projectConfigurable` EPs are in the table below: The attributes supported by `com.intellij.applicationConfigurable` and `com.intellij.projectConfigurable` EPs are in the table below:
| Attribute | Implementation<br/>Basis | Required&ensp;&ensp; | Attribute<br/>Value | | Attribute | Implementation<br/>Basis | Required&ensp;&ensp; | Attribute<br/>Value |
|:-----------------------|:------------------------------------------|:--------------------:|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |:-----------------------|:------------------------------------------|:--------------------:|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `instance` | `Configurable` | (1) | FQN of implementation. See [The Configurable Interface](#the-configurable-interface) for more information. | | `instance` | `Configurable` | (1) | FQN of implementation. See [](#the-configurable-interface) for more information. |
| `provider` | `ConfigurableProvider` | (1) | FQN of implementation. See [The ConfigurableProvider Class](#the-configurableprovider-class) for more information. | | `provider` | `ConfigurableProvider` | (1) | FQN of implementation. See [](#the-configurableprovider-class) for more information. |
| `nonDefaultProject` | `Configurable` | Y | Applicable _only_ to the `com.intellij.projectConfigurable` (project Settings) EP.<br/>`true` = show Settings for all projects _except_ the [default project](https://www.jetbrains.com/help/idea/configure-project-settings.html#new-default-settings).<br/>`false` = show Settings for all projects. | | `nonDefaultProject` | `Configurable` | Y | Applicable _only_ to the `com.intellij.projectConfigurable` (project Settings) EP.<br/>`true` = show Settings for all projects _except_ the [default project](https://www.jetbrains.com/help/idea/configure-project-settings.html#new-default-settings).<br/>`false` = show Settings for all projects. |
| `displayName` | `Configurable`<br/>`ConfigurableProvider` | (2) | The non-localized Settings name visible to users, which is needed for the Settings dialog left-side menu.<br/>For a _localized_ visible name omit `displayName` and use the `key` and `bundle` attributes. | | `displayName` | `Configurable`<br/>`ConfigurableProvider` | (2) | The non-localized Settings name visible to users, which is needed for the Settings dialog left-side menu.<br/>For a _localized_ visible name omit `displayName` and use the `key` and `bundle` attributes. |
| `key` and<br/>`bundle` | `Configurable`<br/>`ConfigurableProvider` | (2) | The [localization](localization_guide.md) key and bundle for the Settings name visible to users.<br/>For non-localized visible names omit `key` and `bundle` and use `displayName`. | | `key` and<br/>`bundle` | `Configurable`<br/>`ConfigurableProvider` | (2) | The [localization](localization_guide.md) key and bundle for the Settings name visible to users.<br/>For non-localized visible names omit `key` and `bundle` and use `displayName`. |
| `id` | `Configurable`<br/>`ConfigurableProvider` | Y | The unique, FQN identifier for this implementation.<br/>The FQN should be based on the plugin `id` to ensure uniqueness. | | `id` | `Configurable`<br/>`ConfigurableProvider` | Y | The unique, FQN identifier for this implementation.<br/>The FQN should be based on the plugin `id` to ensure uniqueness. |
| `parentId` | `Configurable`<br/>`ConfigurableProvider` | Y | This attribute is used to create a hierarchy of Settings. This component is declared one of the specified `parentId` component's children. Typically used for placing a Settings panel within the Settings Dialog menu. Acceptable values for `parentId` are given in [Values for Parent ID Attribute](#values-for-parent-id-attribute).<br/>`groupId` is deprecated.(3) | | `parentId` | `Configurable`<br/>`ConfigurableProvider` | Y | This attribute is used to create a hierarchy of Settings. This component is declared one of the specified `parentId` component's children. Typically used for placing a Settings panel within the Settings Dialog menu. Acceptable values for `parentId` are given in [](#values-for-parent-id-attribute).<br/>`groupId` is deprecated.(3) |
| `groupWeight` | `Configurable`<br/>`ConfigurableProvider` | N | Specifies the weight (stacking order) of this component within the group of a parent configurable component. The default weight is 0, meaning lowest in the order.<br/>If one child in a group or a parent component has non-zero weight, all children will be sorted descending by their weight. If the weights are equal, the components will be sorted ascending by their display name. | | `groupWeight` | `Configurable`<br/>`ConfigurableProvider` | N | Specifies the weight (stacking order) of this component within the group of a parent configurable component. The default weight is 0, meaning lowest in the order.<br/>If one child in a group or a parent component has non-zero weight, all children will be sorted descending by their weight. If the weights are equal, the components will be sorted ascending by their display name. |
| `dynamic` | `Configurable.Composite` | N | This component's children are dynamically calculated by calling the `getConfigurables()` method.<br/>Not recommended because it requires loading additional classes while building a Settings tree. If possible, use XML attributes instead. | | `dynamic` | `Configurable.Composite` | N | This component's children are dynamically calculated by calling the `getConfigurables()` method.<br/>Not recommended because it requires loading additional classes while building a Settings tree. If possible, use XML attributes instead. |
| `childrenEPName` | `Configurable` | N | Specifies the FQN name of the Extension Point that will be used to calculate the children of this component. | | `childrenEPName` | `Configurable` | N | Specifies the FQN name of the Extension Point that will be used to calculate the children of this component. |
@ -75,9 +86,10 @@ The attributes supported by `com.intellij.applicationConfigurable` and `com.inte
**Attribute Notes:** **Attribute Notes:**
1) Either `instance` or `provider` must be specified depending on the implementation. 1) Either `instance` or `provider` must be specified depending on the implementation.
2) One of these attribute sets must be specified depending on whether the displayed Settings name is localized. 2) One of these attribute sets must be specified depending on whether the displayed Settings name is localized.
3) If both `groupId` and `parentId` are specified, a warning is logged. Also, see _default_ entry in [Values for Parent ID Attribute](#values-for-parent-id-attribute). 3) If both `groupId` and `parentId` are specified, a warning is logged. Also, see _default_ entry in [](#values-for-parent-id-attribute).
#### Values for Parent ID Attribute #### Values for Parent ID Attribute
The table below shows the allowed values for the `parentId` attribute. The table below shows the allowed values for the `parentId` attribute.
See the [previous section](#table-of-attributes) for all supported attributes. See the [previous section](#table-of-attributes) for all supported attributes.
@ -95,16 +107,19 @@ See the [previous section](#table-of-attributes) for all supported attributes.
| `project` | Project-related Settings | The IntelliJ Platform no longer uses this group. It was intended to store some project-related settings. Do not use this group. | | `project` | Project-related Settings | The IntelliJ Platform no longer uses this group. It was intended to store some project-related settings. Do not use this group. |
## Implementations for Settings Extension Points ## Implementations for Settings Extension Points
Implementations for `com.intellij.projectConfigurable` and `com.intellij.applicationConfigurable` EPs can have one of two bases: Implementations for `com.intellij.projectConfigurable` and `com.intellij.applicationConfigurable` EPs can have one of two bases:
* The [`Configurable`](upsource:///platform/ide-core/src/com/intellij/openapi/options/Configurable.java) interface, which provides a named configurable component with a Swing form. * The [`Configurable`](upsource:///platform/ide-core/src/com/intellij/openapi/options/Configurable.java) interface, which provides a named configurable component with a Swing form.
Most Settings providers are based on the `Configurable` interface or one of its sub- or supertypes. Most Settings providers are based on the `Configurable` interface or one of its sub- or supertypes.
* The [`ConfigurableProvider`](upsource:///platform/ide-core/src/com/intellij/openapi/options/ConfigurableProvider.java) class, which can hide a configurable component from the Settings dialog based on runtime conditions. * The [`ConfigurableProvider`](upsource:///platform/ide-core/src/com/intellij/openapi/options/ConfigurableProvider.java) class, which can hide a configurable component from the Settings dialog based on runtime conditions.
### The Configurable Interface ### The Configurable Interface
Many Settings in the `intellij-community` code base implement `Configurable` or one of its subtypes, such as [`SearchableConfigurable`](upsource:///platform/ide-core/src/com/intellij/openapi/options/SearchableConfigurable.java). Many Settings in the `intellij-community` code base implement `Configurable` or one of its subtypes, such as [`SearchableConfigurable`](upsource:///platform/ide-core/src/com/intellij/openapi/options/SearchableConfigurable.java).
Readers are encouraged to review the Javadoc comments for `Configurable`. Readers are encouraged to review the Javadoc comments for `Configurable`.
#### Constructors #### Constructors
Implementations must meet several requirements for constructors. Implementations must meet several requirements for constructors.
* Application Settings implementations, declared using the [`applicationConfigurable` EP](#declaring-application-settings), must have a default constructor with no arguments. * Application Settings implementations, declared using the [`applicationConfigurable` EP](#declaring-application-settings), must have a default constructor with no arguments.
* Project Settings implementations, declared using the [`projectConfigurable` EP](#declaring-project-settings), must declare a constructor with a single argument of type [`Project`](upsource:///platform/core-api/src/com/intellij/openapi/project/Project.java). * Project Settings implementations, declared using the [`projectConfigurable` EP](#declaring-project-settings), must declare a constructor with a single argument of type [`Project`](upsource:///platform/core-api/src/com/intellij/openapi/project/Project.java).
@ -117,18 +132,20 @@ For a `Configurable` implementation correctly declared using an EP, the implemen
{type="warning"} {type="warning"}
#### IntelliJ Platform Interactions with Configurable #### IntelliJ Platform Interactions with Configurable
The instantiation of a generic `Configurable` implementation is documented in the interface file. The instantiation of a generic `Configurable` implementation is documented in the interface file.
A few high-level points are reviewed here: A few high-level points are reviewed here:
* The `Configurable.reset()` method is invoked immediately after `Configurable.createComponent()`. * The `Configurable.reset()` method is invoked immediately after `Configurable.createComponent()`.
Initialization of Setting values in the constructor or `createComponent()` is unnecessary. Initialization of Setting values in the constructor or `createComponent()` is unnecessary.
* See the [Constructors](#constructors) section for information about when a Settings object is instantiated. * See the [](#constructors) section for information about when a Settings object is instantiated.
* Once instantiated, a `Configurable` instance's lifetime continues regardless of whether the implementation's Settings are changed, or the user chooses a different entry on the Settings Dialog menu. * Once instantiated, a `Configurable` instance's lifetime continues regardless of whether the implementation's Settings are changed, or the user chooses a different entry on the Settings Dialog menu.
* A `Configurable` instance's lifetime ends when **OK** or **Cancel** is selected in the Settings Dialog. * A `Configurable` instance's lifetime ends when <control>OK</control> or <control>Cancel</control> is selected in the Settings Dialog.
An instance's `Configurable.disposeUIResources()` is called when the Settings Dialog is closing. An instance's `Configurable.disposeUIResources()` is called when the Settings Dialog is closing.
To open Settings dialog or show specific `Configurable`, see [`ShowSettingsUtil`](upsource:///platform/platform-api/src/com/intellij/openapi/options/ShowSettingsUtil.java). To open Settings dialog or show specific `Configurable`, see [`ShowSettingsUtil`](upsource:///platform/platform-api/src/com/intellij/openapi/options/ShowSettingsUtil.java).
#### Configurable Marker Interfaces #### Configurable Marker Interfaces
Implementations based on `Configurable` can implement marker interfaces, which provide additional flexibility in the implementation. Implementations based on `Configurable` can implement marker interfaces, which provide additional flexibility in the implementation.
The following nested interfaces are markers, which convey information about the form to the IntelliJ Platform: The following nested interfaces are markers, which convey information about the form to the IntelliJ Platform:
@ -140,11 +157,13 @@ The following nested interfaces are markers, which convey information about the
By default, an empty border is added for a plugin's Settings component. By default, an empty border is added for a plugin's Settings component.
#### Additional Interfaces Based on Configurable #### Additional Interfaces Based on Configurable
There are classes in the IntelliJ Platform specialized for particular types of Settings.
There are classes in the IntelliJ Platform specialized in particular types of Settings.
These subtypes are based on `com.intellij.openapi.options.ConfigurableEP`. These subtypes are based on `com.intellij.openapi.options.ConfigurableEP`.
For example, <menupath>Settings/Preferences | Editor | General | Appearance</menupath> allows adding Settings via [`EditorSmartKeysConfigurableEP`](upsource:///platform/lang-impl/src/com/intellij/application/options/editor/EditorSmartKeysConfigurableEP.java) and `com.intellij.editorSmartKeysConfigurable` EP. For example, <menupath>Settings/Preferences | Editor | General | Appearance</menupath> allows adding Settings via [`EditorSmartKeysConfigurableEP`](upsource:///platform/lang-impl/src/com/intellij/application/options/editor/EditorSmartKeysConfigurableEP.java) and `com.intellij.editorSmartKeysConfigurable` EP.
### The ConfigurableProvider Class ### The ConfigurableProvider Class
The [`ConfigurableProvider`](upsource:///platform/ide-core/src/com/intellij/openapi/options/ConfigurableProvider.java) class only provides a `Configurable` implementation if its runtime conditions are met. The [`ConfigurableProvider`](upsource:///platform/ide-core/src/com/intellij/openapi/options/ConfigurableProvider.java) class only provides a `Configurable` implementation if its runtime conditions are met.
The IntelliJ Platform first calls the `ConfigurableProvider.canCreateConfigurable()`, which evaluates runtime conditions to determine if Settings changes make sense in the current context. The IntelliJ Platform first calls the `ConfigurableProvider.canCreateConfigurable()`, which evaluates runtime conditions to determine if Settings changes make sense in the current context.
If the Settings make sense to display, `canCreateConfigurable()` returns `true`. If the Settings make sense to display, `canCreateConfigurable()` returns `true`.