diff --git a/platform/platform-impl/src/com/intellij/openapi/options/binding/BindableConfigurable.java b/platform/platform-impl/src/com/intellij/openapi/options/binding/BindableConfigurable.java
deleted file mode 100644
index a4956ccc3726..000000000000
--- a/platform/platform-impl/src/com/intellij/openapi/options/binding/BindableConfigurable.java
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
-
-package com.intellij.openapi.options.binding;
-
-import com.intellij.openapi.options.ConfigurationException;
-import com.intellij.openapi.options.UnnamedConfigurable;
-import org.jetbrains.annotations.ApiStatus;
-
-import javax.swing.*;
-
-/**
- * @author Dmitry Avdeev
- *
- * @deprecated Use {@see com.intellij.openapi.options.BoundConfigurable} instead
- */
-@ApiStatus.Internal
-@Deprecated(forRemoval = true)
-public abstract class BindableConfigurable implements UnnamedConfigurable {
-
- protected ControlBinder myBinder;
-
- protected BindableConfigurable(ControlBinder binder) {
- myBinder = binder;
- }
-
- protected BindableConfigurable() {
-
- }
-
- protected void bindAnnotations() {
- getBinder().bindAnnotations(this);
- }
-
- protected void bindControl(JComponent control, String propertyName, boolean instant) {
- getBinder().bindControl(control, propertyName, instant);
- }
-
- protected void bindControl(ControlValueAccessor controlAccessor, String propertyName, boolean instant) {
- getBinder().bindControl(controlAccessor, propertyName, instant);
- }
-
- @Override
- public boolean isModified() {
- return getBinder().isModified();
- }
-
- @Override
- public void apply() throws ConfigurationException {
- getBinder().apply();
- }
-
- @Override
- public void reset() {
- getBinder().reset();
- }
-
- protected ControlBinder getBinder() {
- return myBinder;
- }
-}
diff --git a/platform/tasks-platform-impl/resources/messages/TaskBundle.properties b/platform/tasks-platform-impl/resources/messages/TaskBundle.properties
index 45b7c9a05e50..2daf48dad553 100644
--- a/platform/tasks-platform-impl/resources/messages/TaskBundle.properties
+++ b/platform/tasks-platform-impl/resources/messages/TaskBundle.properties
@@ -34,9 +34,9 @@ settings.connection.timeout=Connection &timeout:
settings.milliseconds=milliseconds
settings.always.display.task.combo.in.toolbar=Show task &widget if there are no active tasks
settings.save.context.on.commit=&Save context on commit
-settings.issue.cache=Issue cache
+settings.issue.cache=Issue Cache
settings.enable.cache=&Enable cache
-settings.Update=\ &Update
+settings.Update=&Update
settings.issues.every=issues e&very
settings.minutes=minutes
settings.change.list.name.format.should.not.be.empty=Change list name format should not be empty
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskConfigurable.form b/plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskConfigurable.form
deleted file mode 100644
index c55ad549abbd..000000000000
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskConfigurable.form
+++ /dev/null
@@ -1,239 +0,0 @@
-
-
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskConfigurable.kt b/plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskConfigurable.kt
index 60b5ac74e844..70c557a140a7 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskConfigurable.kt
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskConfigurable.kt
@@ -1,225 +1,202 @@
-// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
-package com.intellij.tasks.config;
+// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package com.intellij.tasks.config
-import com.intellij.icons.AllIcons;
-import com.intellij.openapi.command.WriteCommandAction;
-import com.intellij.openapi.fileTypes.FileType;
-import com.intellij.openapi.fileTypes.FileTypeManager;
-import com.intellij.openapi.fileTypes.PlainTextFileType;
-import com.intellij.openapi.options.Configurable;
-import com.intellij.openapi.options.ConfigurationException;
-import com.intellij.openapi.options.SearchableConfigurable;
-import com.intellij.openapi.options.binding.BindControl;
-import com.intellij.openapi.options.binding.BindableConfigurable;
-import com.intellij.openapi.options.binding.ControlBinder;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.project.ProjectManager;
-import com.intellij.openapi.ui.popup.JBPopupFactory;
-import com.intellij.openapi.ui.popup.PopupStep;
-import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
-import com.intellij.openapi.util.NotNullLazyValue;
-import com.intellij.tasks.CommitPlaceholderProvider;
-import com.intellij.tasks.TaskBundle;
-import com.intellij.tasks.TaskManager;
-import com.intellij.tasks.TaskRepository;
-import com.intellij.tasks.impl.BaseRepositoryImpl;
-import com.intellij.tasks.impl.TaskManagerImpl;
-import com.intellij.ui.EditorTextField;
-import com.intellij.ui.ExtendableEditorSupport;
-import com.intellij.ui.components.JBCheckBox;
-import com.intellij.ui.components.JBTextField;
-import com.intellij.ui.components.fields.ExtendableTextComponent;
-import com.intellij.util.ArrayUtilRt;
-import org.jetbrains.annotations.NotNull;
+import com.intellij.icons.AllIcons
+import com.intellij.openapi.command.WriteCommandAction
+import com.intellij.openapi.editor.ex.EditorEx
+import com.intellij.openapi.fileTypes.FileTypeManager
+import com.intellij.openapi.fileTypes.PlainTextFileType
+import com.intellij.openapi.options.BoundSearchableConfigurable
+import com.intellij.openapi.options.Configurable
+import com.intellij.openapi.options.Configurable.NoScroll
+import com.intellij.openapi.options.ConfigurationException
+import com.intellij.openapi.options.SearchableConfigurable
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.project.ProjectManager
+import com.intellij.openapi.ui.DialogPanel
+import com.intellij.openapi.ui.popup.JBPopupFactory
+import com.intellij.openapi.ui.popup.PopupStep
+import com.intellij.openapi.ui.popup.util.BaseListPopupStep
+import com.intellij.tasks.CommitPlaceholderProvider
+import com.intellij.tasks.TaskBundle
+import com.intellij.tasks.TaskManager
+import com.intellij.tasks.impl.BaseRepositoryImpl
+import com.intellij.tasks.impl.TaskManagerImpl
+import com.intellij.ui.EditorSettingsProvider
+import com.intellij.ui.EditorTextField
+import com.intellij.ui.ExtendableEditorSupport
+import com.intellij.ui.components.fields.ExtendableTextComponent
+import com.intellij.ui.dsl.builder.*
+import kotlin.reflect.KMutableProperty0
-import javax.swing.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Objects;
-import java.util.Set;
+class TaskConfigurable(private val project: Project) : BoundSearchableConfigurable(
+ TaskBundle.message("configurable.TaskConfigurable.display.name"),
+ "reference.settings.project.tasks", "tasks"), SearchableConfigurable.Parent, NoScroll {
-/**
- * @author Dmitry Avdeev
- */
-@SuppressWarnings({"UnusedDeclaration"})
-public class TaskConfigurable extends BindableConfigurable implements SearchableConfigurable.Parent, Configurable.NoScroll {
- private JPanel myPanel;
+ private val changelistNameFormat: EditorTextField
+ private val branchNameFormat: EditorTextField
- @BindControl("updateEnabled")
- private JCheckBox myUpdateCheckBox;
+ private val lazyConfigurables: Array by lazy { arrayOf(TaskRepositoriesConfigurable(project)) }
- @BindControl("updateIssuesCount")
- private JTextField myUpdateCount;
+ init {
+ val fileType = FileTypeManager.getInstance().findFileTypeByName("VTL") ?: PlainTextFileType.INSTANCE
+ val defaultProject = ProjectManager.getInstance().getDefaultProject()
+ branchNameFormat = EditorTextField(defaultProject, fileType)
+ setupAddAction(branchNameFormat)
+ changelistNameFormat = EditorTextField(defaultProject, fileType)
+ setupAddAction(changelistNameFormat)
- @BindControl("updateInterval")
- private JTextField myUpdateInterval;
+ }
- @BindControl("taskHistoryLength")
- private JTextField myHistoryLength;
- private JPanel myCacheSettings;
+ override fun createPanel(): DialogPanel {
+ val settings = TaskSettings.getInstance()
+ val config = getConfig()
- @BindControl("saveContextOnCommit")
- private JCheckBox mySaveContextOnCommit;
-
- @BindControl("changelistNameFormat")
- private EditorTextField myChangelistNameFormat;
-
- private JBCheckBox myAlwaysDisplayTaskCombo;
- private JTextField myConnectionTimeout;
-
- @BindControl("branchNameFormat")
- private EditorTextField myBranchNameFormat;
- private JCheckBox myLowerCase;
- private JBTextField myReplaceSpaces;
-
- private final Project myProject;
- private Configurable[] myConfigurables;
- private final NotNullLazyValue myControlBinder;
-
- public TaskConfigurable(Project project) {
- super();
- myProject = project;
- myUpdateCheckBox.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- enableCachePanel();
+ return panel {
+ row(TaskBundle.message("settings.changelist.name.format")) {
+ cell(changelistNameFormat)
+ .bindText(config::changelistNameFormat)
+ .align(AlignX.FILL)
}
- });
- myControlBinder = NotNullLazyValue.lazy(() -> new ControlBinder(getConfig()));
- }
+ row(TaskBundle.message("settings.feature.branch.name.format")) {
+ cell(branchNameFormat)
+ .bindText(config::branchNameFormat)
+ .align(AlignX.FILL)
+ }
+ row("") {
+ checkBox(TaskBundle.message("settings.lowercased"))
+ .bindSelected(settings::LOWER_CASE_BRANCH)
+ .resizableColumn()
- private TaskManagerImpl.Config getConfig() {
- return ((TaskManagerImpl)TaskManager.getManager(myProject)).getState();
- }
+ textField()
+ .bindText(settings::REPLACE_SPACES)
+ .columns(1)
+ .label(TaskBundle.message("settings.replace.spaces.with"))
+ }
+ row(TaskBundle.message("settings.task.history.length")) {
+ intTextField()
+ .columns(COLUMNS_TINY)
+ .bindIntText(config::taskHistoryLength)
+ }
+ row(TaskBundle.message("settings.connection.timeout")) {
+ intTextField()
+ .columns(COLUMNS_TINY)
+ .bindIntText(settings::CONNECTION_TIMEOUT)
+ .gap(RightGap.SMALL)
- @Override
- protected ControlBinder getBinder() {
- return myControlBinder.getValue();
- }
+ @Suppress("DialogTitleCapitalization")
+ label(TaskBundle.message("settings.milliseconds"))
+ }
+ row {
+ checkBox(TaskBundle.message("settings.always.display.task.combo.in.toolbar"))
+ .bindSelected(settings::ALWAYS_DISPLAY_COMBO)
+ }
+ row {
+ checkBox(TaskBundle.message("settings.save.context.on.commit"))
+ .bindSelected(config::saveContextOnCommit)
+ }
- private void enableCachePanel() {
- myUpdateCount.setEnabled(myUpdateCheckBox.isSelected());
- myUpdateInterval.setEnabled(myUpdateCheckBox.isSelected());
- }
+ group(TaskBundle.message("settings.issue.cache")) {
+ row {
+ val updateCheckBox = checkBox(TaskBundle.message("settings.enable.cache"))
+ .bindSelected(config::updateEnabled)
- @Override
- public void reset() {
- super.reset();
- enableCachePanel();
- myAlwaysDisplayTaskCombo.setSelected(TaskSettings.getInstance().ALWAYS_DISPLAY_COMBO);
- myConnectionTimeout.setText(Integer.toString(TaskSettings.getInstance().CONNECTION_TIMEOUT));
- myLowerCase.setSelected(TaskSettings.getInstance().LOWER_CASE_BRANCH);
- myReplaceSpaces.setText(TaskSettings.getInstance().REPLACE_SPACES);
- }
+ intTextField()
+ .bindIntText(config::updateIssuesCount)
+ .enabledIf(updateCheckBox.selected)
+ .label(TaskBundle.message("settings.Update"))
+ .columns(4)
+ .gap(RightGap.SMALL)
- @Override
- public void apply() throws ConfigurationException {
- if (myChangelistNameFormat.getText().trim().isEmpty()) {
- throw new ConfigurationException(TaskBundle.message("settings.change.list.name.format.should.not.be.empty"));
- }
- if (myBranchNameFormat.getText().trim().isEmpty()) {
- throw new ConfigurationException(TaskBundle.message("settings.Branch.name.format.should.not.be.empty"));
- }
- boolean oldUpdateEnabled = getConfig().updateEnabled;
- super.apply();
- TaskSettings.getInstance().ALWAYS_DISPLAY_COMBO = myAlwaysDisplayTaskCombo.isSelected();
- int oldConnectionTimeout = TaskSettings.getInstance().CONNECTION_TIMEOUT;
- int connectionTimeout = Integer.parseInt(myConnectionTimeout.getText());
- TaskSettings.getInstance().CONNECTION_TIMEOUT = connectionTimeout;
- TaskSettings.getInstance().LOWER_CASE_BRANCH = myLowerCase.isSelected();
- TaskSettings.getInstance().REPLACE_SPACES = myReplaceSpaces.getText();
+ @Suppress("DialogTitleCapitalization")
+ intTextField()
+ .bindIntText(config::updateInterval)
+ .enabledIf(updateCheckBox.selected)
+ .label(TaskBundle.message("settings.issues.every"))
+ .columns(4)
+ .gap(RightGap.SMALL)
- if (myProject.isDefault()) return;
- TaskManager manager = TaskManager.getManager(myProject);
- if (getConfig().updateEnabled && !oldUpdateEnabled) {
- manager.updateIssues(null);
- }
- if (connectionTimeout != oldConnectionTimeout) {
- for (TaskRepository repository : manager.getAllRepositories()) {
- if (repository instanceof BaseRepositoryImpl) {
- ((BaseRepositoryImpl)repository).reconfigureClient();
+ @Suppress("DialogTitleCapitalization")
+ label(TaskBundle.message("settings.minutes"))
+ .enabledIf(updateCheckBox.selected)
}
}
}
}
- @Override
- public boolean isModified() {
- return super.isModified() ||
- TaskSettings.getInstance().ALWAYS_DISPLAY_COMBO != myAlwaysDisplayTaskCombo.isSelected() ||
- TaskSettings.getInstance().CONNECTION_TIMEOUT != Integer.parseInt(myConnectionTimeout.getText()) ||
- TaskSettings.getInstance().LOWER_CASE_BRANCH != myLowerCase.isSelected() ||
- !Objects.equals(TaskSettings.getInstance().REPLACE_SPACES, myReplaceSpaces.getText());
- }
-
- @Override
- public String getDisplayName() {
- return TaskBundle.message("configurable.TaskConfigurable.display.name");
- }
-
- @Override
- public String getHelpTopic() {
- return "reference.settings.project.tasks";
- }
-
- @Override
- public JComponent createComponent() {
- bindAnnotations();
- return myPanel;
- }
-
- @Override
- public @NotNull String getId() {
- return "tasks";
- }
-
- @Override
- public boolean hasOwnContent() {
- return true;
- }
-
- @Override
- public Configurable @NotNull [] getConfigurables() {
- if (myConfigurables == null) {
- myConfigurables = new Configurable[] { new TaskRepositoriesConfigurable(myProject) };
+ @Throws(ConfigurationException::class)
+ override fun apply() {
+ if (changelistNameFormat.getText().trim().isEmpty()) {
+ throw ConfigurationException(TaskBundle.message("settings.change.list.name.format.should.not.be.empty"))
}
- return myConfigurables;
- }
+ if (branchNameFormat.getText().trim().isEmpty()) {
+ throw ConfigurationException(TaskBundle.message("settings.Branch.name.format.should.not.be.empty"))
+ }
- private void createUIComponents() {
- FileType fileType = FileTypeManager.getInstance().findFileTypeByName("VTL");
- if (fileType == null) {
- fileType = PlainTextFileType.INSTANCE;
+ val oldConnectionTimeout = TaskSettings.getInstance().CONNECTION_TIMEOUT
+ val oldUpdateEnabled = getConfig().updateEnabled
+
+ super.apply()
+
+ if (project.isDefault()) {
+ return
+ }
+
+ val manager = TaskManager.getManager(project)
+ if (getConfig().updateEnabled && !oldUpdateEnabled) {
+ manager.updateIssues(null)
+ }
+
+ if (TaskSettings.getInstance().CONNECTION_TIMEOUT != oldConnectionTimeout) {
+ for (repository in manager.getAllRepositories()) {
+ if (repository is BaseRepositoryImpl) {
+ repository.reconfigureClient()
+ }
+ }
}
- Project project = ProjectManager.getInstance().getDefaultProject();
- myBranchNameFormat = new EditorTextField(project, fileType);
- setupAddAction(myBranchNameFormat);
- myChangelistNameFormat = new EditorTextField(project, fileType);
- setupAddAction(myChangelistNameFormat);
}
- private void setupAddAction(EditorTextField field) {
- field.addSettingsProvider(editor -> {
- ExtendableTextComponent.Extension extension =
+ override fun getConfigurables(): Array {
+ return lazyConfigurables
+ }
+
+ override fun hasOwnContent(): Boolean {
+ return true
+ }
+
+ private fun getConfig(): TaskManagerImpl.Config {
+ return (TaskManager.getManager(project) as TaskManagerImpl).getState()
+ }
+
+ private fun setupAddAction(field: EditorTextField) {
+ field.addSettingsProvider(EditorSettingsProvider { editor: EditorEx ->
+ val extension =
ExtendableTextComponent.Extension
- .create(AllIcons.General.InlineAdd, AllIcons.General.InlineAddHover, TaskBundle.message("settings.add.placeholder"), () -> {
- Set placeholders = new HashSet<>();
- for (CommitPlaceholderProvider provider : CommitPlaceholderProvider.EXTENSION_POINT_NAME.getExtensionList()) {
- placeholders.addAll(Arrays.asList(provider.getPlaceholders(null)));
- }
- JBPopupFactory.getInstance().createListPopup(new BaseListPopupStep<>(TaskBundle.message("settings.placeholders"),
- ArrayUtilRt.toStringArray(placeholders)) {
- @Override
- public PopupStep> onChosen(String selectedValue, boolean finalChoice) {
- WriteCommandAction.runWriteCommandAction(myProject, () -> editor.getDocument()
- .insertString(editor.getCaretModel().getOffset(), "${" + selectedValue + "}"));
- return FINAL_CHOICE;
+ .create(AllIcons.General.InlineAdd, AllIcons.General.InlineAddHover, TaskBundle.message("settings.add.placeholder"), Runnable {
+ val placeholders = HashSet()
+ for (provider in CommitPlaceholderProvider.EXTENSION_POINT_NAME.extensionList) {
+ placeholders.addAll(provider.getPlaceholders(null))
}
- }).showInBestPositionFor(editor);
- });
- ExtendableEditorSupport.setupExtension(editor, field.getBackground(), extension);
- });
+ JBPopupFactory.getInstance().createListPopup(object : BaseListPopupStep(TaskBundle.message("settings.placeholders"),
+ placeholders.toList()) {
+ override fun onChosen(selectedValue: String?, finalChoice: Boolean): PopupStep<*> {
+ WriteCommandAction.runWriteCommandAction(project, Runnable {
+ editor.getDocument()
+ .insertString(editor.getCaretModel().offset, "\${$selectedValue}")
+ })
+ return FINAL_CHOICE
+ }
+ }).showInBestPositionFor(editor)
+ })
+ ExtendableEditorSupport.setupExtension(editor, field.getBackground(), extension)
+ })
+ }
+
+ private fun Cell.bindText(prop: KMutableProperty0): Cell {
+ return bind(
+ componentGet = { component -> component.getText() },
+ componentSet = { component, value -> component.setText(value) },
+ prop = prop.toMutableProperty()
+ )
}
}