From 76262309fa2cf1c1c26b53928006aee7c482cf15 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Tue, 8 Aug 2017 12:37:07 +0200 Subject: [PATCH] IDEA-173109 Typing settings repository URL triggers path alert --- .../diagnostic/JetBrainsAccountDialog.kt | 3 +- .../com/intellij/ui/components/components.kt | 9 ++---- .../resources/messages/IcsBundle.properties | 2 +- .../src/IcsSettingsPanel.java | 19 ++++-------- .../src/RepositoryService.kt | 13 ++++---- .../src/readOnlySourcesEditor.kt | 30 +++++++++++-------- .../settings-repository/src/upstreamEditor.kt | 26 +++++++--------- 7 files changed, 46 insertions(+), 56 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.kt b/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.kt index cc009b7cd6f6..9ebe8bc438f0 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.kt +++ b/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.kt @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -62,5 +62,6 @@ fun showJetBrainsAccountDialog(parent: Component, project: Project? = null): Dia if (!userName.isNullOrBlank()) { PasswordSafe.getInstance().set(CredentialAttributes(ErrorReportConfigurable.SERVICE_NAME, userName), Credentials(userName, if (rememberCheckBox.isSelected) passwordField.password else null)) } + return@dialog true } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ui/components/components.kt b/platform/platform-impl/src/com/intellij/ui/components/components.kt index 8cd9fd56c942..fdfb7a6c221f 100644 --- a/platform/platform-impl/src/com/intellij/ui/components/components.kt +++ b/platform/platform-impl/src/com/intellij/ui/components/components.kt @@ -141,7 +141,7 @@ fun dialog(title: String, parent: Component? = null, errorText: String? = null, modality: IdeModalityType = IdeModalityType.IDE, - ok: (() -> Unit)? = null): DialogWrapper { + ok: (() -> Boolean)? = null): DialogWrapper { return object: DialogWrapper(project, parent, true, modality) { init { setTitle(title) @@ -161,12 +161,9 @@ fun dialog(title: String, override fun getPreferredFocusedComponent() = focusedComponent override fun doOKAction() { - ok?.let { - if (okAction.isEnabled) { - it() - } + if (okAction.isEnabled && (ok == null || ok())) { + super.doOKAction() } - super.doOKAction() } } } diff --git a/plugins/settings-repository/resources/messages/IcsBundle.properties b/plugins/settings-repository/resources/messages/IcsBundle.properties index 0147c44bf099..c177f214e544 100644 --- a/plugins/settings-repository/resources/messages/IcsBundle.properties +++ b/plugins/settings-repository/resources/messages/IcsBundle.properties @@ -16,7 +16,7 @@ action.CommitToIcs.text=Commit to Settings Repository init.dialog.message=There is no Settings Repository in the {0}, would you like to create a new one in this location? init.dialog.title=Create Settings Repository -specify.absolute.path.dialog.message=Please specify absolute path +specify.absolute.path.dialog.message=Path is not absolute init.failed.title=Cannot Init Repository init.failed.message=Failed to init repository: {0} diff --git a/plugins/settings-repository/src/IcsSettingsPanel.java b/plugins/settings-repository/src/IcsSettingsPanel.java index aa8a94c3fb58..83df819dbfd4 100644 --- a/plugins/settings-repository/src/IcsSettingsPanel.java +++ b/plugins/settings-repository/src/IcsSettingsPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,16 +20,18 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.TextBrowseFolderListener; import com.intellij.openapi.ui.TextFieldWithBrowseButton; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.ui.DocumentAdapter; import kotlin.Unit; import kotlin.jvm.functions.Function0; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import javax.swing.event.DocumentEvent; +/** + * We do not use DialogWrapper validation because UI is awful (located below the field with the same font). + * To fix https://youtrack.jetbrains.com/issue/IDEA-173109 "Typing settings repository URL triggers path alert", + * we simply do validation on button action (and never disable button). + */ public class IcsSettingsPanel extends DialogWrapper { private JPanel panel; private TextFieldWithBrowseButton urlTextField; @@ -49,15 +51,6 @@ public class IcsSettingsPanel extends DialogWrapper { } }); - urlTextField.getTextField().getDocument().addDocumentListener(new DocumentAdapter() { - @Override - protected void textChanged(DocumentEvent e) { - UpstreamEditorKt.updateSyncButtonState(StringUtil.nullize(urlTextField.getText()), syncActions); - } - }); - - UpstreamEditorKt.updateSyncButtonState(StringUtil.nullize(urlTextField.getText()), syncActions); - setTitle(IcsBundleKt.icsMessage("settings.panel.title")); setResizable(false); init(); diff --git a/plugins/settings-repository/src/RepositoryService.kt b/plugins/settings-repository/src/RepositoryService.kt index cd6d978c4657..43340bdc63dd 100644 --- a/plugins/settings-repository/src/RepositoryService.kt +++ b/plugins/settings-repository/src/RepositoryService.kt @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,7 @@ import java.nio.file.Path import java.nio.file.Paths interface RepositoryService { - fun checkUrl(uriString: String, suggestToCreate: Boolean, project: Project? = null): Boolean { + fun checkUrl(uriString: String, project: Project? = null): Boolean { val uri = URIish(uriString) val isFile: Boolean if (uri.scheme == URLUtil.FILE_PROTOCOL) { @@ -50,8 +50,7 @@ interface RepositoryService { val file = Paths.get(if (url.endsWith(suffix)) url.substring(0, url.length - suffix.length) else url) if (file.exists()) { if (!file.isDirectory()) { - //noinspection DialogTitleCapitalization - Messages.showErrorDialog(project, "Specified path is not a directory", "Specified Path is Invalid") + Messages.showErrorDialog(project, "Path is not a directory", "") return false } else if (isValidRepository(file)) { @@ -68,13 +67,13 @@ interface RepositoryService { .yesText("Create") .project(project) .isYes) { - try { + return try { createBareRepository(file) - return true + true } catch (e: IOException) { Messages.showErrorDialog(project, icsMessage("init.failed.message", e.message), icsMessage("init.failed.title")) - return false + false } } else { diff --git a/plugins/settings-repository/src/readOnlySourcesEditor.kt b/plugins/settings-repository/src/readOnlySourcesEditor.kt index d9438f57ff7a..f2d611670529 100644 --- a/plugins/settings-repository/src/readOnlySourcesEditor.kt +++ b/plugins/settings-repository/src/readOnlySourcesEditor.kt @@ -20,23 +20,21 @@ import com.intellij.openapi.diagnostic.runAndLogException import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory import com.intellij.openapi.options.ConfigurableUi import com.intellij.openapi.progress.runModalTask -import com.intellij.openapi.ui.DialogBuilder import com.intellij.openapi.ui.TextBrowseFolderListener import com.intellij.openapi.ui.TextFieldWithBrowseButton -import com.intellij.ui.DocumentAdapter +import com.intellij.ui.components.dialog +import com.intellij.ui.layout.* import com.intellij.util.Function import com.intellij.util.containers.ContainerUtil import com.intellij.util.io.delete import com.intellij.util.io.exists import com.intellij.util.text.nullize import com.intellij.util.text.trimMiddle -import com.intellij.util.ui.FormBuilder import com.intellij.util.ui.table.TableModelEditor import gnu.trove.THashSet import org.jetbrains.settingsRepository.git.asProgressMonitor import org.jetbrains.settingsRepository.git.cloneBare import javax.swing.JTextField -import javax.swing.event.DocumentEvent private val COLUMNS = arrayOf(object : TableModelEditor.EditableColumnInfo() { override fun getColumnClass() = Boolean::class.java @@ -62,19 +60,25 @@ internal fun createReadOnlySourcesEditor(): ConfigurableUi { override fun getItemClass() = ReadonlySource::class.java override fun edit(item: ReadonlySource, mutator: Function, isAdd: Boolean) { - val dialogBuilder = DialogBuilder() val urlField = TextFieldWithBrowseButton(JTextField(20)) urlField.addBrowseFolderListener(TextBrowseFolderListener(FileChooserDescriptorFactory.createSingleFolderDescriptor())) - urlField.textField.document.addDocumentListener(object : DocumentAdapter() { - override fun textChanged(event: DocumentEvent) { - dialogBuilder.setOkActionEnabled(checkUrl(urlField.text.nullize())) - } - }) - dialogBuilder.title("Add read-only source").resizable(false).centerPanel(FormBuilder.createFormBuilder().addLabeledComponent("URL:", urlField).panel).setPreferredFocusComponent(urlField) - if (dialogBuilder.showAndGet()) { - mutator.`fun`(item).url = urlField.text + val panel = panel { + row("URL:") { + urlField() + } } + + dialog(title = "Add read-only source", panel = panel, focusedComponent = urlField) { + val url = urlField.text.nullize(true) + if (!validateUrl(url, null)) { + return@dialog false + } + + mutator.`fun`(item).url = url + return@dialog true + } + .show() } override fun applyEdited(oldItem: ReadonlySource, newItem: ReadonlySource) { diff --git a/plugins/settings-repository/src/upstreamEditor.kt b/plugins/settings-repository/src/upstreamEditor.kt index 15d4bf3935f4..ff7c98c1154a 100644 --- a/plugins/settings-repository/src/upstreamEditor.kt +++ b/plugins/settings-repository/src/upstreamEditor.kt @@ -23,7 +23,6 @@ import com.intellij.openapi.ui.Messages import com.intellij.openapi.ui.TextFieldWithBrowseButton import com.intellij.openapi.util.SystemInfo import com.intellij.openapi.util.text.StringUtil -import com.intellij.util.ArrayUtil import com.intellij.util.text.nullize import org.jetbrains.settingsRepository.actions.NOTIFICATION_GROUP import java.awt.Container @@ -31,26 +30,23 @@ import java.awt.event.ActionEvent import javax.swing.AbstractAction import javax.swing.Action -internal fun checkUrl(url: String?): Boolean { - try { - return url != null && url.length > 1 && icsManager.repositoryService.checkUrl(url, false) - } - catch (e: Throwable) { +fun validateUrl(url: String?, project: Project?): Boolean { + if (url == null) { + Messages.showErrorDialog(project, "URL is empty", "") return false } -} -fun updateSyncButtonState(url: String?, syncActions: Array) { - val enabled = checkUrl(url) - for (syncAction in syncActions) { - syncAction.isEnabled = enabled + if (!icsManager.repositoryService.checkUrl(url, project)) { + return false } + + return true } fun createMergeActions(project: Project?, urlTextField: TextFieldWithBrowseButton, dialogParent: Container, okAction: (() -> Unit)): Array { var syncTypes = SyncType.values() if (SystemInfo.isMac) { - syncTypes = ArrayUtil.reverseArray(syncTypes) + syncTypes = syncTypes.reversedArray() } val icsManager = icsManager @@ -59,8 +55,8 @@ fun createMergeActions(project: Project?, urlTextField: TextFieldWithBrowseButto val syncType = syncTypes[it] object : AbstractAction(icsMessage("action.${if (syncType == SyncType.MERGE) "Merge" else (if (syncType == SyncType.OVERWRITE_LOCAL) "ResetToTheirs" else "ResetToMy")}Settings.text")) { private fun saveRemoteRepositoryUrl(): Boolean { - val url = urlTextField.text.nullize() - if (url != null && !icsManager.repositoryService.checkUrl(url, true, project)) { + val url = urlTextField.text.nullize(true) + if (!validateUrl(url, project)) { return false } @@ -71,7 +67,7 @@ fun createMergeActions(project: Project?, urlTextField: TextFieldWithBrowseButto } override fun actionPerformed(event: ActionEvent) { - ActionsCollector.getInstance().record("Ics." + getValue(Action.NAME)) + ActionsCollector.getInstance().record("Ics.${getValue(Action.NAME)}") val repositoryWillBeCreated = !icsManager.repositoryManager.isRepositoryExists() var upstreamSet = false try {