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() + ) } }