[settings] add suite of content IJSDK-150

Remove unrelated changes
           Feedback from PR#280
           Fine tune panel definition
This commit is contained in:
JohnHake 2020-04-24 14:27:29 -07:00
parent c9e8650f2b
commit 82180ae103
21 changed files with 977 additions and 5 deletions

6
.idea/gradle.xml generated
View File

@ -92,6 +92,11 @@
<project path="$PROJECT_DIR$/code_samples/run_configuration" />
</projects>
</build>
<build path="$PROJECT_DIR$/code_samples/settings" name="settings">
<projects>
<project path="$PROJECT_DIR$/code_samples/settings" />
</projects>
</build>
<build path="$PROJECT_DIR$/code_samples/simple_language_plugin" name="simple_language_plugin">
<projects>
<project path="$PROJECT_DIR$/code_samples/simple_language_plugin" />
@ -134,6 +139,7 @@
<option value="$PROJECT_DIR$/code_samples/project_wizard" />
<option value="$PROJECT_DIR$/code_samples/psi_demo" />
<option value="$PROJECT_DIR$/code_samples/run_configuration" />
<option value="$PROJECT_DIR$/code_samples/settings" />
<option value="$PROJECT_DIR$/code_samples/simple_language_plugin" />
<option value="$PROJECT_DIR$/code_samples/tool_window" />
<option value="$PROJECT_DIR$/code_samples/tree_structure_provider" />

View File

@ -84,10 +84,13 @@
* [Actions Tutorial](tutorials/action_system.md)
* [Creating Actions](tutorials/action_system/working_with_custom_actions.md)
* [Grouping Actions](tutorials/action_system/grouping_action.md)
* [Settings](basics/settings.md)
* [Persistence](basics/persistence.md)
* [Persisting State of Components](basics/persisting_state_of_components.md)
* [Persisting Sensitive Data](basics/persisting_sensitive_data.md)
* Editing Settings
* [Settings](basics/settings.md)
* [Settings Guide](reference_guide/settings_guide.md)
* [Custom Groups](reference_guide/settings_groups.md)
* [Settings Tutorial](tutorials/settings_tutorial.md)
* [Files](basics/architectural_overview/files.md)
* [Virtual File System](basics/virtual_file_system.md)
* [Virtual Files](basics/architectural_overview/virtual_file.md)

11
basics/persistence.md Normal file
View File

@ -0,0 +1,11 @@
---
title: Persistence Model
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
The IntelliJ Platform Persistence Model is used to store a variety of information.
For example, [Run Configurations](run_configurations.md) and [Settings](settings.md) are stored using the Persistence Model.
There are two distinct approaches, depending on the type of data being persisted:
* [Persisting State of Components](/basics/persisting_state_of_components.md)
* [Persisting Sensitive Data](/basics/persisting_sensitive_data.md)

View File

@ -3,6 +3,10 @@ title: Settings
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
* [Persisting State of Components](/basics/persisting_state_of_components.md)
* [Persisting Sensitive Data](/basics/persisting_sensitive_data.md)
* Editing Settings
## Introduction to Settings
[Settings](https://www.jetbrains.com/help/idea/configuring-project-and-ide-settings.html) are but one application of the IntelliJ Platform [Persistence Model](/basics/persistence.md).
For more information, see:
* [Settings Guide](/reference_guide/settings_guide.md) for information about Settings Extension Points and implementations.
* [Custom Settings Groups](/reference_guide/settings_groups.md) for information about creating custom Settings groups and parent-child relationships.
* [Settings Tutorial](/tutorials/settings_tutorial.md) for step-by-step instructions for creating a simple set of custom Settings.

View File

@ -21,6 +21,7 @@ includeBuild '../project_view_pane'
includeBuild '../project_wizard'
includeBuild '../psi_demo'
includeBuild '../run_configuration'
includeBuild '../settings'
includeBuild '../simple_language_plugin'
includeBuild '../tool_window'
includeBuild '../tree_structure_provider'

View File

@ -0,0 +1,21 @@
plugins {
id 'java'
id 'org.jetbrains.intellij' version '0.4.18'
}
group 'org.intellij.sdk'
version '0.1'
repositories {
mavenCentral()
}
// See https://github.com/JetBrains/gradle-intellij-plugin/
intellij {
version '2020.1'
sameSinceUntilBuild = true
}
patchPluginXml {
version = project.version
}

Binary file not shown.

View File

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

183
code_samples/settings/gradlew vendored Executable file
View File

@ -0,0 +1,183 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"

100
code_samples/settings/gradlew.bat vendored Normal file
View File

@ -0,0 +1,100 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -0,0 +1,2 @@
rootProject.name = 'settings'

View File

@ -0,0 +1,54 @@
// Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.intellij.sdk.settings;
import com.intellij.ui.components.JBCheckBox;
import com.intellij.ui.components.JBLabel;
import com.intellij.ui.components.JBTextField;
import com.intellij.util.ui.FormBuilder;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
/**
* This class has responsibility for creating and managing a JPanel for the Settings Dialog.
*/
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);
}
}

View File

@ -0,0 +1,67 @@
// Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.intellij.sdk.settings;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurationException;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
/**
* Provides controller functionality for application settings.
* See com.intellij.openapi.options.Configurable for additional documentation.
*/
public class AppSettingsConfigurable implements Configurable {
private AppSettingsComponent mySettingsComponent = null;
// 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() throws ConfigurationException {
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;
}
}

View File

@ -0,0 +1,42 @@
// Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.intellij.sdk.settings;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.util.xmlb.XmlSerializerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* This class is responsible for storing the application settings in a persistent way.
* The State and Storage macros define the name of the data and the file name where
* these persistent application settings are stored.
*/
@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 ServiceManager.getService(AppSettingsState.class);
}
@Nullable
@Override
public AppSettingsState getState() {
return this;
}
@Override
public void loadState(@NotNull AppSettingsState state) {
XmlSerializerUtil.copyBean(state, this);
}
}

View File

@ -0,0 +1,39 @@
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
<idea-plugin>
<!-- Unique id for this plugin. Must stay constant for the life of the plugin. -->
<id>org.intellij.sdk.settings</id>
<!-- Text to display as name on Preferences/Settings | Plugin page -->
<name>SDK: Settings Example Project</name>
<!-- please see https://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/plugin_compatibility.html
on how to target different products -->
<depends>com.intellij.modules.platform</depends>
<!-- Text to display as description on Preferences/Settings | Plugin page -->
<description>
<![CDATA[
Demonstrates implementing a custom settings panel.<br>Adds a settings panel to the <b>Settings/Preferences</b> panel under <b>Tools</b>.
]]>
</description>
<change-notes>
<![CDATA[
<ul>
<li><b>1.0</b> Initial SDK settings content release for 2020.1</li>
</ul>
]]>
</change-notes>
<!-- Text to display as company information on Preferences/Settings | Plugin page -->
<vendor url="https://plugins.jetbrains.com">IntelliJ Platform SDK</vendor>
<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>
</idea-plugin>

View File

@ -0,0 +1,63 @@
<svg xmlns="http://www.w3.org/2000/svg" width="81" height="80" viewBox="0 0 81 80">
<defs>
<linearGradient id="pluginsdk_80-a" x1="-.031%" x2="100.053%" y1="49.963%" y2="49.963%">
<stop offset="25.81%" stop-color="#F97A12"/>
<stop offset="45.91%" stop-color="#B07B58"/>
<stop offset="72.41%" stop-color="#577BAE"/>
<stop offset="91.05%" stop-color="#1E7CE5"/>
<stop offset="100%" stop-color="#087CFA"/>
</linearGradient>
<linearGradient id="pluginsdk_80-b" x1="27.55%" x2="82.223%" y1="34.514%" y2="77.605%">
<stop offset="0%" stop-color="#F97A12"/>
<stop offset="7.18%" stop-color="#CB7A3E"/>
<stop offset="15.41%" stop-color="#9E7B6A"/>
<stop offset="24.2%" stop-color="#757B91"/>
<stop offset="33.44%" stop-color="#537BB1"/>
<stop offset="43.24%" stop-color="#387CCC"/>
<stop offset="53.81%" stop-color="#237CE0"/>
<stop offset="65.52%" stop-color="#147CEF"/>
<stop offset="79.25%" stop-color="#0B7CF7"/>
<stop offset="100%" stop-color="#087CFA"/>
</linearGradient>
<linearGradient id="pluginsdk_80-c" x1="63.121%" x2="40.793%" y1="97.699%" y2="-6.587%">
<stop offset="0%" stop-color="#FE315D"/>
<stop offset="7.84%" stop-color="#CB417E"/>
<stop offset="16.01%" stop-color="#9E4E9B"/>
<stop offset="24.74%" stop-color="#755BB4"/>
<stop offset="33.92%" stop-color="#5365CA"/>
<stop offset="43.65%" stop-color="#386DDB"/>
<stop offset="54.14%" stop-color="#2374E9"/>
<stop offset="65.76%" stop-color="#1478F3"/>
<stop offset="79.4%" stop-color="#0B7BF8"/>
<stop offset="100%" stop-color="#087CFA"/>
</linearGradient>
<linearGradient id="pluginsdk_80-d" x1="25.331%" x2="93.854%" y1="24.119%" y2="132.621%">
<stop offset="0%" stop-color="#FE315D"/>
<stop offset="4.023%" stop-color="#F63462"/>
<stop offset="10.37%" stop-color="#DF3A71"/>
<stop offset="16.67%" stop-color="#C24383"/>
<stop offset="29.12%" stop-color="#AD4A91"/>
<stop offset="54.98%" stop-color="#755BB4"/>
<stop offset="91.75%" stop-color="#1D76ED"/>
<stop offset="100%" stop-color="#087CFA"/>
</linearGradient>
</defs>
<g fill="none" fill-rule="evenodd">
<g fill-rule="nonzero" transform="translate(8 8)">
<path fill="url(#pluginsdk_80-a)"
d="M6.08754566,64 L2.66453526e-15,59.1000946 L0,26.7918961 L30,38.6703369 L10.1403967,64 L6.08754566,64 Z"/>
<path fill="url(#pluginsdk_80-b)"
d="M20.9524706,64 L52.2740919,31.9159091 L37.6708832,0.460194805 L38.0580944,1.33226763e-15 L64,0 L64,64 L20.9524706,64 Z"/>
<path fill="url(#pluginsdk_80-c)"
d="M34.4123783,0 L64,0 L64,28.0366227 L49.0078336,44 L34,0.44696173 L34.4123783,0 Z"/>
<path fill="url(#pluginsdk_80-d)"
d="M30.3358775,64 L0,64 L0,49.9709549 L6.23437817,29.2830519 L0,27.1596093 L0,0 L39.4697238,0 L58,21.3844805 L30.5381317,63.9259091 L30.3358775,64 Z"/>
</g>
<g fill-rule="nonzero" transform="translate(12 12)">
<rect width="56" height="56" fill="#000"/>
<rect width="22" height="4" x="4" y="46" fill="#FFFEFE"/>
<path fill="#FFFEFE"
d="M11.128,25.28 C8.584,25.28 6.016,24.392 4,22.592 L6.184,19.976 C7.696,21.224 9.28,22.016 11.2,22.016 C12.712,22.016 13.624,21.416 13.624,20.432 L13.624,20.384 C13.624,19.448 13.048,18.968 10.24,18.248 C6.856,17.384 4.672,16.448 4.672,13.112 L4.672,13.064 C4.672,10.016 7.12,8 10.552,8 C13,8 15.088,8.768 16.792,10.136 L14.872,12.92 C13.384,11.888 11.92,11.264 10.504,11.264 C9.088,11.264 8.344,11.912 8.344,12.728 L8.344,12.776 C8.344,13.88 9.064,14.24 11.968,14.984 C15.376,15.872 17.296,17.096 17.296,20.024 L17.296,20.072 C17.296,23.408 14.752,25.28 11.128,25.28 Z M19.512,25.04 L19.512,8.24 L26.064,8.24 C31.344,8.24 34.992,11.864 34.992,16.592 L34.992,16.64 C34.992,21.368 31.344,25.04 26.064,25.04 L19.512,25.04 Z M26.064,11.576 L23.208,11.576 L23.208,21.704 L26.064,21.704 C29.088,21.704 31.128,19.664 31.128,16.688 L31.128,16.64 C31.128,13.664 29.088,11.576 26.064,11.576 Z M37.28,25.04 L37.28,8.24 L40.976,8.24 L40.976,15.584 L47.744,8.24 L52.28,8.24 L45.416,15.368 L52.568,25.04 L48.128,25.04 L42.92,17.888 L40.976,19.904 L40.976,25.04 L37.28,25.04 Z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -0,0 +1,94 @@
---
title: Custom Settings Groups
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
As described in [Extension Points for Settings](settings_guide.md#extension-points-for-settings), custom _Settings_ can be declared as children of existing parent groups such as `tools`.
These parent groups are the existing categories of Settings in the IntelliJ Platform-based IDE.
However, suppose the custom Settings are rich enough to require multiple levels?
For example, a custom Setting implementation has multiple sub-Settings implementations.
Extension Point declarations can create this kind of multilayer Settings hierarchy.
* bullet list
{:toc}
## Extension Points for Parent-Child Settings Relationships
There are multiple ways of creating parent-child relationships in groups of Settings: in implementations, or Extension Point declarations.
However, there are performance penalties for creating these relationships in implementations because the objects must be instantiated to determine the relationships.
This section describes the syntax for declaring more complex parent-child relationships in `com.intellij.projectConfigurable` or `com.intellij.applicationConfigurable` EPs.
> **Note** An application configurable can be a parent of a project configurable.
There are two ways of declaring parent-child relationships using the `com.intellij.projectConfigurable` or `com.intellij.applicationConfigurable` EPs.
The first is to use separate EP declarations that are tied together by the value of one attribute.
The second method is to use nested declarations.
### Parent-Child Settings Using Separate EPs
One way of declaring a parent-child relationship is by using two separate declarations.
This form can be used regardless of whether the parent Settings declaration is in the same plugin.
If the `id` attribute of the parent is known, a plugin can add Settings as a child of that parent.
For example, below are two declarations for project Settings.
The first gets added to the `tools` group, and the second gets added to the `id` of the parent.
The `id` of the second, child `<projectConfigurable>` adds a suffix (`servers`) to the `id` of the parent.
```xml
<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>
```
See the [Attributes for Parent-Child Settings EPs](#attributes-for-parent-child-settings-eps) section for details about the suffix `id`.
### Parent-Child Settings Using Nested EPs
A shorthand for the separate declaration approach is using the `com.intellij.configurable` EP.
This approach nests the child's Settings declaration within the `com.intellij.projectConfigurable` or `com.intellij.applicationConfigurable` EP.
Using `<configurable>` EP would not be possible if the parent Settings were declared in another plugin or file.
In that case, [Parent-Child Settings Using Separate EPs](#parent-child-settings-using-separate-eps) would be used.
When using `<configurable>` EP there isn't a `parentId` for the child because the nesting implies it.
As with using separate EP declarations, formatting restrictions are placed on the child's `id` attribute - the suffix (`servers`) gets added.
See the [Attributes for Parent-Child Settings EPs](#attributes-for-parent-child-settings-eps) section.
The example below demonstrates a `<configurable>` EP declaration:
```xml
<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>
```
Within the parent `<projectConfigurable>` EP declaration above, more `<configurable>` declarations could be added as sibling Settings.
### Attributes for Parent-Child Settings EPs
There is only one unique attribute when declaring a child Settings EP.
The other attributes are the same as discussed in [Settings EP Attributes](settings_guide.md#settings-declaration-attributes).
For the child of a parent, the `id` attribute becomes compound:
| Attribute | Required | Value |
|:--- | :---: |:--- |
| `id` | Y | Compound FQN of implementation based on `com.intellij.openapi.options.Configurable` in the form: `XX.YY` where:<br>`XX` is the parent Settings component FQN-based id.<br>`YY` is unique to the child among other siblings. |
> **Tip** All children share the parent's `id` as the basis of their own `id`. All children have an `id` suffix that is unique among their siblings.
## Implementations for Parent-Child Settings
Implementations can be based on [`Configurable`](upsource:///platform/platform-api/src/com/intellij/openapi/options/Configurable.java), [`ConfigurableProvider`](upsource:///platform/platform-api/src/com/intellij/openapi/options/ConfigurableProvider.java) or one of their subtypes.
For more information about creating Settings implementations, see [Implementations for Settings Extension Points](settings_guide.md#implementations-for-settings-extension-points).
### Configurable Marker Interfaces
The `Configurable.Composite` interface indicates a configurable component has child components.
The preferred approach is to specify child components in the [EP declaration](#extension-points-for-parent-child-settings-relationships).
Using the `Composite` interface incurs the penalty of loading child classes while building the tree of Settings Swing components.

View File

@ -0,0 +1,152 @@
---
title: Settings Guide
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
_Settings_ persistently store states that control the behavior and appearance of IntelliJ Platform-based IDEs.
On this page, the term "Settings" means the same as "Preferences" on some platforms.
Plugins can create and store Settings to capture their configuration in a way that uses the IntelliJ Platform [Persistence Model](/basics/persisting_state_of_components.md).
The User Interface (UI) for these custom Settings can be added to the [IDE Settings dialog](https://www.jetbrains.com/help/idea/settings-preferences-dialog.html).
Settings can [affect different levels](https://www.jetbrains.com/help/idea/configuring-project-and-ide-settings.html) of scope.
This document describes adding custom Settings at the Project and Application (or Global, IDE) levels.
* bullet list
{:toc}
## Extension Points for Settings
Custom Settings implementations are declared in a plugin's configuration (`plugin.xml`) file using one of two Extension Points (EPs), depending on the level of the Settings.
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/platform-api/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.
>**Note** For performance reasons, the recommended approach is to declare as much information as possible about a Settings' implementation using attributes in the Extension Point. If it is not declared, the component must be loaded to retrieve it from the implementation, degrading UI responsiveness.
### Declaring Application Settings
Settings at the Application level use the `com.intellij.applicationConfigurable` EP.
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".
See [Settings Declaration Attributes](#settings-declaration-attributes) for more information.
```xml
<extensions defaultExtensionNs="com.intellij">
<applicationConfigurable parentId="tools" instance="org.company.ApplicationSettingsConfigurable"
id="org.company.ApplicationSettingsConfigurable" displayName="My Application Settings"/>
</extensions>
```
### Declaring Project Settings
Project level Settings use the `com.intellij.projectConfigurable` EP.
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).
See [Settings Declaration Attributes](#settings-declaration-attributes) for details.
```xml
<extensions defaultExtensionNs="com.intellij">
<projectConfigurable parentId="tools" instance="org.company.ProjectSettingsConfigurable"
id="org.company.ProjectSettingsConfigurable" displayName="My Project Settings"
nonDefaultProject="true"/>
</extensions>
```
### Settings Declaration Attributes
Readers are encouraged to review the Javadoc comments for [`Configurable`](upsource:///platform/platform-api/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.
#### Table of Attributes
The attributes supported by `com.intellij.applicationConfigurable` and `com.intellij.projectConfigurable` EPs are in the table below:
| Attribute |Implementation<br>Basis |Required&ensp; |&ensp; &ensp; Attribute Value |
| :---------- | :----- | :--------: |:------ |
| `instance` | `Configurable` | (1) | FQN of implementation. See [The Configurable Interface](#the-configurable-interface) for more information. |
| `provider` | `ConfigurableProvider` | (1) | FQN of implementation. See [The ConfigurableProvider Class](#the-configurableprovider-class) for more information. |
| `nonDefaultProject`&ensp; | `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. |
| `key` and<br>`bundle` | `Configurable`<br>`ConfigurableProvider` | (2) | The [localization](/reference_guide/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. |
| `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) |
| `groupWeight` | `Configurable`<br>`ConfigurableProvider` | | 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` | | 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` | | Specifies the FQN name of the Extension Point that will be used to calculate the children of this component. |
**Attribute Notes:**
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.
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.
See the [previous section](#table-of-attributes) for all supported attributes.
| `parentId` Value | Group | Details |
| :--------------- | :---- | :------ |
|_default_ | `other` | If neither `parentId` nor `groupId` attribute is set, the component is added to the `other` Settings group. This is undesirable; see `other` group description. |
|`appearance` | Appearance & Behavior | This child group contains Settings to personalize IDE appearance, such as: changing themes and font size. Also, it covers Settings to customize behavior such as keymaps, configuring plugins, and system Settings such as password policies, HTTP proxy, updates, and more. |
|`build` | Build, Execution, Deployment | Child group containing Settings to configure project integration with different build tools, modify the default compiler Settings, manage server access configurations, customize the debugger behavior, etc. |
|`build.tools`&nbsp;| Build Integration | A subgroup of `build`. This subgroup configures project integration with build tools such as Maven, Gradle, or Gant. |
|`editor` | Editor | Child group containing Settings to personalize source code appearance, such as fonts, highlighting styles, indents, etc. It also contains Settings to customize the editor's appearance, such as line numbers, caret placement, tabs, source code inspections, setting up templates, and file encodings. | |
|`language` | Languages and Frameworks | Child group containing Settings related to specific language frameworks and technologies used in the project. |
|`tools` | 3rd Party Settings | Child group containing Settings to configure integration with third-party applications, specify the SSH Terminal connection Settings, manage server certificates and tasks, configure diagrams layout, etc. |
|`root` | Super Parent | The invisible parent of all existing groups. Not used except for IDEs built on top of the IntelliJ Platform, or extensive suites of Settings. You should not place settings in this group. |
|`other` | Catch-all | The IntelliJ Platform no longer uses this group. It was a catch-all child category containing Settings related to non-bundled custom plugins that are not assigned to any other category. Use the `tools` group instead. |
|`project` | Project-related Settings | The IntelliJ Platform no longer uses this group. It was intended to store some project-related settings. You should not place settings in this group. |
## Implementations for Settings Extension Points
Implementations for `com.intellij.projectConfigurable` and `com.intellij.applicationConfigurable` EPs can have one of two bases:
* The [`Configurable`](upsource:///platform/platform-api/src/com/intellij/openapi/options/Configurable.java) interface, which provides a named configurable component with a Swing form.
Most of the Settings providers in the `intellij-community` code base are based on the `Configurable` interface or one of its sub- or supertypes.
* The [`ConfigurableProvider`](upsource:///platform/platform-api/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
Many Settings in the `intellij-community` code base implement `Configurable` or one of its subtypes, such as [`SearchableConfigurable`](upsource:///platform/platform-api/src/com/intellij/openapi/options/SearchableConfigurable.java).
Readers are encouraged to review the Javadoc comments for `Configurable`.
#### Constructors
Implementations must meet several requirements for constructors.
* Application Settings implementations, declared using the [`applicationConfiguration` EP](#declaring-application-settings), must have a default constructor with no arguments.
* Project Settings implementations, declared using the [`projectSettings` 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).
For a `Configurable` implementation correctly declared using an EP, the implementation's constructor is not called by the IntelliJ Platform until a user chooses the corresponding Settings `displayName` in the Settings Dialog menu.
For performance reasons, do not create any Swing components in a constructor.
> **Warning** The IntelliJ Platform may instantiate a `Configurable` implementation on a background thread, so creating Swing components in a constructor can degrade UI responsiveness.
#### IntelliJ Platform Interactions with Configurable
Interactions between the IntelliJ Platform and a generic implementation of the `Configurable` interface are documented in the source file.
A few high-level points are reviewed here:
* After calling `Configurable.createComponent()`, the IntelliJ Platform immediately calls `Configurable.reset()` to initialize the values of the Settings.
So 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.
* Once instantiated, a `Configurable` instance is valid until the user presses **OK** or **Cancel** in the Settings Dialog.
* The object's lifetime continues regardless of whether the implementation's Settings are changed, or the user chooses a different entry on the Settings Dialog menu.
* The IntelliJ Platform calls an implementation's `Configurable.disposeUIResources()` when the Settings dialog is closing.
#### Configurable Marker Interfaces
Implementations based on `Configurable` can have nested interfaces, which provide additional flexibility in the implementation.
See the `Configurable` interface file for details.
The following nested interfaces are markers, which convey information about the form to the IntelliJ Platform:
* `Configurable.NoScroll` - Notifies the Settings dialog not to add scroll bars to the form.
By default, a plugin's Settings component is put into a scrollable pane.
However, a Settings panel can have a `JTree`, which requires its own `JScrollPane`.
So `NoScroll` interface should be used to remove the outer `JScrollPane`.
* `Configurable.NoMargin` - Notifies the Settings dialog not to add an empty border to the form.
By default, an empty border is added for a plugin's Settings component.
#### Additional Interfaces Based on Configurable
There are classes in the IntelliJ Platform specialized for particular types of Settings.
These subtypes are based on `com.intellij.openapi.options.ConfigurableEP`.
For example, **Settings/Preferences \| Editor \| General \|Appearance** 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`](upsource:///platform/platform-api/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.
If the Settings make sense to display, `canCreateConfigurable()` returns `true`.
In that case the IntelliJ Platform calls `ConfigurableProvider.createConfigurable()`, which returns the `Configurable` object for its Settings implementation.
By choosing not to provide a `Configuration` implementation in some circumstances, the `ConfigurableProvider` opts out of the Settings display and modification process.
The use of `ConfigurableProvider` as a basis for a Settings implementation is declared using [attributes](#table-of-attributes) in the EP declaration.

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

View File

@ -0,0 +1,125 @@
---
title: Settings Tutorial
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
## Introduction
As discussed in the [_Settings_ Guide](/reference_guide/settings_guide.md), plugins can add Settings to IntelliJ Platform-based IDEs.
The IDE displays the Settings in response to a user choosing **Settings/Preferences**.
Custom Settings are displayed and function just like those native to the IDE.
* bullet list
{:toc}
## Overview of a Custom Settings Implementation
Using the SDK code sample [`settings`](https://github.com/JetBrains/intellij-sdk-docs/tree/master/code_samples/settings), this tutorial illustrates the steps to create custom Application-level Settings.
Many IntelliJ Platform Settings implementations use fewer classes, but the `settings` code sample factors the functionality into three classes for clarity :
* The [`AppSettingsConfigurable`](https://github.com/JetBrains/intellij-sdk-docs/tree/master/code_samples/settings/src/main/java/org/intellij/sdk/settings/AppSettingsConfigurable.java) is analogous to a Controller in the MVC model - it interacts with the other two Settings classes and the IntelliJ Platform,
* The [`AppSettingsState`](https://github.com/JetBrains/intellij-sdk-docs/tree/master/code_samples/settings/src/main/java/org/intellij/sdk/settings/AppSettingsState.java) is like a Model because it stores the Settings persistently,
* The [`AppSettingsComponent`](https://github.com/JetBrains/intellij-sdk-docs/tree/master/code_samples/settings/src/main/java/org/intellij/sdk/settings/AppSettingsComponent.java) is similar to a View because it displays and captures edits to the values of the Settings.
The structure of the implementation is the same for Project Settings, but there are minor differences in the [`Configurable` implementation](/reference_guide/settings_guide.md#constructors) and [Extension Point (EP) declaration](/reference_guide/settings_guide.md#declaring-project-settings).
## The AppSettingsState Class
The `AppSettingsState` class persistently stores the custom Settings.
It is based on the [IntelliJ Platform Persistence Model](/basics/persisting_state_of_components.md#using-persistentstatecomponent).
### Declaring AppSettingsState
Given a [Light Service](/basics/plugin_structure/plugin_services.md#light-services) is not used, the persistent data class must be declared as a [Service](/basics/plugin_structure/plugin_services.md#how-to-declare-a-service) EP in the `plugin.xml` file.
If these were Project Settings, the `com.intellij.projectService` EP would be used.
However, because these are Application Settings, the `com.intellij.applicationService` EP is used with the FQN of the implementation class:
```xml
<extensions defaultExtensionNs="com.intellij">
<applicationService serviceImplementation="org.intellij.sdk.settings.AppSettingsState"/>
</extensions>
```
### Creating the AppSettingState Implementation
As discussed in [Implementing the PersistentStateComponent Interface](/basics/persisting_state_of_components.md#implementing-the-persistentstatecomponent-interface), `AppSettingsState` uses the pattern of implementing [`PersistentStateComponent`](upsource:///platform/projectModel-api/src/com/intellij/openapi/components/PersistentStateComponent.java) itself:
```java
{% include /code_samples/settings/src/main/java/org/intellij/sdk/settings/AppSettingsState.java %}
```
#### Storage Macro
The [`@State`](upsource:///platform/projectModel-api/src/com/intellij/openapi/components/State.java) macro, located just above the class declaration, [defines the data storage location](/basics/persisting_state_of_components.md#defining-the-storage-location).
For `AppSettingsState`, the data `name` parameter is the FQN of the class.
Using FQN is a best practice to follow, and is required if custom data gets stored in the standard project or workspace files.
The `storages` parameter utilizes the [`@Storage`](upsource:///platform/projectModel-api/src/com/intellij/openapi/components/Storage.java) macro to define a custom file name for the `AppSettingsState` data.
In this case, the file is located in the `options` directory of the [configuration directory](https://www.jetbrains.com/help/idea/tuning-the-ide.html?_ga=2.150184054.1363126807.1588191212-22652347.1575391521#config-directory) for the IDE.
#### Persistent Data Fields
The `AppSettingState` implementation has two public fields: a `String` and a `boolean`.
Conceptually these fields hold the name of a user, and whether that person is an IntelliJ IDEA user, respectively.
See [Implementing the State Class](/basics/persisting_state_of_components.md#implementing-the-state-class) for more information about how `PersistentStateComponent` serializes public fields.
#### AppSettingState Methods
The fields are so limited and straightforward for this class that encapsulation is not used for simplicity.
All that's needed for functionality is to override the two methods called by the IntelliJ Platform when a new component state is loaded (`PersistentStateComponent.loadState()`), and when a state is saved (`PersistentStateComponent.getState()`).
See `PersistentStateComponent` for more information about these methods.
One static convenience method has been added - `AppSettingState.getInstance()` - which allows `AppSettingsConfigurable` to easily acquire a reference to `AppSettingState`.
## The AppSettingsComponent Class
The role of the [`AppSettingsComponent`](https://github.com/JetBrains/intellij-sdk-docs/tree/master/code_samples/settings/src/main/java/org/intellij/sdk/settings/AppSettingsComponent.java) is to provide a `JPanel` for the custom Settings to the IDE Settings Dialog.
The `AppSettingsComponent` has-a `JPanel`, and is responsible for its lifetime.
The `AppSettingsComponent` is instantiated by `AppSettingsConfigurable`.
### Creating the AppSettingsComponent Implementation
The `AppSettingsComponent` defines a `JPanel` containing a [`JBTextField`](upsource:///platform/platform-api/src/com/intellij/ui/components/JBTextField.java) and a [`JBCheckBox`](upsource:///platform/platform-api/src/com/intellij/ui/components/JBCheckBox.java) to hold and display the data that maps to the [data fields](#persistent-data-fields) of `AppSettingsState`:
```java
{% include /code_samples/settings/src/main/java/org/intellij/sdk/settings/AppSettingsComponent.java %}
```
#### AppSettingsComponent Methods
The constructor builds the `JPanel` using the convenient [`FormBuilder`](upsource:///platform/platform-api/src/com/intellij/util/ui/FormBuilder.java), and saves a reference to the `JPanel`.
The rest of the class are simple accessors and mutators to encapsulate the UI components used on the `JPanel`.
## The AppSettingsConfigurable Class
The methods of [`AppSettingsConfigurable`](https://github.com/JetBrains/intellij-sdk-docs/tree/master/code_samples/settings/src/main/java/org/intellij/sdk/settings/AppSettingsConfigurable.java) are called by the IntelliJ Platform, and `AppSettingsConfigurable` in turn interacts with `AppSettingsComponent` and `AppSettingState`.
### Declaring the AppSettingsConfigurable
As described in [Declaring Application Settings](/reference_guide/settings_guide.md#declaring-application-settings), the `com.intellij.applicationConfigurable` is used as the EP.
An explanation of this declaration can be found in [Declaring Application Settings](/reference_guide/settings_guide.md#declaring-application-settings):
```xml
<extensions defaultExtensionNs="com.intellij">
<applicationConfigurable parentId="tools" instance="org.intellij.sdk.settings.AppSettingsConfigurable"
id="org.intellij.sdk.settings.AppSettingsConfigurable"
displayName="SDK: Application Settings Example"/>
</extensions>
```
### Creating the AppSettingsConfigurable Implementation
The `AppSettingsConfigurable` class implements [`Configurable`](upsource:///platform/platform-api/src/com/intellij/openapi/options/Configurable.java) interface.
The class has one field to hold a reference to the `AppSettingsComponent`.
```java
{% include /code_samples/settings/src/main/java/org/intellij/sdk/settings/AppSettingsConfigurable.java %}
```
#### AppSettingsConfigurable Methods
All the methods in this class are overrides of the methods in the `Configurable` interface.
Readers are encouraged to review the Javadoc comments for the `Configurable` methods.
Also review notes about [IntelliJ Platform Interactions](/reference_guide/settings_guide.md#intellij-platform-interactions-with-configurable) with `Configurable` methods.
## Testing the Custom Settings Plugin
After performing the steps described above, compile and run the plugin in a Development Instance to see the custom Settings available in the Settings Dialog.
Open the IDE Settings by selecting **Settings/Preferences \| Tools \| SDK: Application Settings Example**.
The settings are preloaded with the default values:
!["Settings Defaults"](img/settings_defaults.png){:width="600px"}
Now edit the settings values to "John Doe" and click the checkbox.
Click on the **OK** button to close the Settings dialog and save the changes.
Exit the Development Instance.
Open the file `SdkSettingsPlugin.xml` to see the Settings persistently stored.
In this demonstration the file resides in `code_samples/settings/build/idea-sandbox/config/options/`, but see [IDE Development Instances](/basics/ide_development_instance.md) for the general Development Instance case, or [Default IDE directories](https://www.jetbrains.com/help/idea/tuning-the-ide.html?_ga=2.146292852.1769557795.1588604136-22652347.1575391521#default-dirs) if you are testing the `settings` plugin directly in an IDE.
!["Persisted Settings"](img/settings_persisted.png){:width="600px"}