From 4afb5f6795dd90a6a403b63330822daa835d64fe Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Wed, 7 Sep 2016 12:06:16 +0200 Subject: [PATCH] fix ITN (regression after last change) correctly set focused component to password field if user specified --- .../credentialStore/CredentialAttributes.kt | 3 +- .../com/intellij/openapi/ui/dialogBuilder.kt | 18 ++- .../intellij/util/net/AuthenticationForm.form | 23 ++-- .../com/intellij/diagnostic/ITNReporter.kt | 3 +- .../intellij/diagnostic/IdeErrorsDialog.java | 2 +- .../diagnostic/JetBrainsAccountDialog.kt | 103 ++++++------------ .../diagnostic/JetBrainsAccountForm.form | 92 ---------------- .../src/com/intellij/ui/layout/flags.kt | 63 +++++++++++ .../src/com/intellij/ui/layout/layout.kt | 69 +++++------- .../src/messages/DiagnosticBundle.properties | 7 +- plugins/settings-repository/src/authForm.kt | 2 +- 11 files changed, 152 insertions(+), 233 deletions(-) delete mode 100644 platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountForm.form create mode 100644 platform/platform-impl/src/com/intellij/ui/layout/flags.kt diff --git a/platform/platform-api/src/com/intellij/credentialStore/CredentialAttributes.kt b/platform/platform-api/src/com/intellij/credentialStore/CredentialAttributes.kt index 27d55c4e8ff0..94603d24c42f 100644 --- a/platform/platform-api/src/com/intellij/credentialStore/CredentialAttributes.kt +++ b/platform/platform-api/src/com/intellij/credentialStore/CredentialAttributes.kt @@ -54,7 +54,8 @@ class Credentials(user: String?, val password: OneTimeString? = null) { fun CredentialAttributes(requestor: Class<*>, userName: String?) = CredentialAttributes(requestor.name, userName, requestor) -fun Credentials?.isFulfilled() = this != null && userName != null && password != null +fun Credentials?.isFulfilled() = this != null && userName != null && !password.isNullOrEmpty() +fun Credentials?.hasOnlyUserName() = this != null && userName != null && password.isNullOrEmpty() fun Credentials?.isEmpty() = this == null || (userName == null && password == null) diff --git a/platform/platform-api/src/com/intellij/openapi/ui/dialogBuilder.kt b/platform/platform-api/src/com/intellij/openapi/ui/dialogBuilder.kt index 3c771baaeb96..9790d75fa561 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/dialogBuilder.kt +++ b/platform/platform-api/src/com/intellij/openapi/ui/dialogBuilder.kt @@ -21,21 +21,29 @@ import javax.swing.JComponent fun dialog(title: String, centerPanel: JComponent, - resizable: Boolean = true, + resizable: Boolean = false, preferedFocusComponent: JComponent? = null, okActionEnabled: Boolean = true, project: Project? = null, - parent: Component? = null): DialogBuilder { + parent: Component? = null, + ok: (() -> Unit)? = null): DialogBuilder { val builder = if (parent == null) DialogBuilder(project) else DialogBuilder(parent) builder .title(title) .centerPanel(centerPanel) .setPreferredFocusComponent(preferedFocusComponent) - if (!resizable) { - builder.resizable(false) - } + builder.resizable(resizable) if (!okActionEnabled) { builder.okActionEnabled(false) } + + if (ok != null) { + builder.setOkOperation { + if (builder.dialogWrapper.okAction.isEnabled) { + ok() + builder.dialogWrapper.close(DialogWrapper.OK_EXIT_CODE) + } + } + } return builder } \ No newline at end of file diff --git a/platform/platform-api/src/com/intellij/util/net/AuthenticationForm.form b/platform/platform-api/src/com/intellij/util/net/AuthenticationForm.form index 9efc82b5b5de..a83ab08ef5f0 100644 --- a/platform/platform-api/src/com/intellij/util/net/AuthenticationForm.form +++ b/platform/platform-api/src/com/intellij/util/net/AuthenticationForm.form @@ -1,18 +1,16 @@
- + - - + - - + @@ -20,8 +18,7 @@ - - + @@ -29,8 +26,7 @@ - - + @@ -38,8 +34,7 @@ - - + @@ -47,8 +42,7 @@ - - + @@ -56,8 +50,7 @@ - - + diff --git a/platform/platform-impl/src/com/intellij/diagnostic/ITNReporter.kt b/platform/platform-impl/src/com/intellij/diagnostic/ITNReporter.kt index efd64ed10afc..55a5459fbd10 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/ITNReporter.kt +++ b/platform/platform-impl/src/com/intellij/diagnostic/ITNReporter.kt @@ -16,6 +16,7 @@ package com.intellij.diagnostic import com.intellij.CommonBundle +import com.intellij.credentialStore.hasOnlyUserName import com.intellij.errorreport.bean.ErrorBean import com.intellij.errorreport.error.InternalEAPException import com.intellij.errorreport.error.NoSuchEAPUserException @@ -97,7 +98,7 @@ private fun showYesNoDialog(parentComponent: Component, project: Project?, messa private fun submit(event: IdeaLoggingEvent, parentComponent: Component, callback: Consumer, errorBean: ErrorBean, description: String?): Boolean { var credentials = ErrorReportConfigurable.getCredentials() // ask password only if user name was specified - if (credentials?.userName != null && credentials?.password.isNullOrEmpty()) { + if (credentials.hasOnlyUserName()) { if (!showJetBrainsAccountDialog(parentComponent).showAndGet()) { return false } diff --git a/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java b/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java index e1c4f4394eeb..ce56c4c5e326 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java +++ b/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java @@ -347,7 +347,7 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene @Override public void hyperlinkUpdate(HyperlinkEvent e) { if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { - JetBrainsAccountDialogKt.showJetBrainsAccountDialog(getRootPane(), null).show(); + JetBrainsAccountDialogKt.showJetBrainsAccountDialog(getRootPane()).show(); updateCredentialsPane(getSelectedMessage()); } } diff --git a/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.kt b/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.kt index eefbe9514dff..c45e06a9d4f8 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.kt +++ b/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.kt @@ -15,97 +15,58 @@ */ package com.intellij.diagnostic +import com.intellij.CommonBundle import com.intellij.credentialStore.CredentialAttributes import com.intellij.credentialStore.Credentials -import com.intellij.ide.BrowserUtil import com.intellij.ide.passwordSafe.PasswordSafe import com.intellij.openapi.project.Project import com.intellij.openapi.ui.DialogBuilder -import com.intellij.openapi.ui.DialogWrapper import com.intellij.openapi.ui.dialog -import com.intellij.openapi.util.text.StringUtil -import com.intellij.ui.ClickListener +import com.intellij.openapi.ui.ex.MultiLineLabel +import com.intellij.ui.components.JBCheckBox import com.intellij.ui.layout.* +import com.intellij.ui.layout.CCFlags.* import com.intellij.ui.layout.LCFlags.* import com.intellij.util.net.HttpConfigurable import java.awt.Component -import java.awt.Cursor -import java.awt.event.MouseEvent -import javax.swing.* +import javax.swing.JPasswordField +import javax.swing.JTextField +@JvmOverloads fun showJetBrainsAccountDialog(parent: Component, project: Project? = null): DialogBuilder { + val credentials = ErrorReportConfigurable.getCredentials() + val userField = JTextField(credentials?.userName) + val passwordField = JPasswordField(credentials?.password?.toString()) + + // if no user name - never stored and so, defaults to remember. if user name set, but no password, so, previously was stored without password + val rememberCheckBox = JBCheckBox(CommonBundle.message("checkbox.remember.password"), credentials?.userName == null || !credentials?.password.isNullOrEmpty()) + val panel = panel(fillX) { - label(DiagnosticBundle.message("diagnostic.error.report.description")) - link(DiagnosticBundle.message("diagnostic.error.report.proxy.setup")) { + MultiLineLabel(DiagnosticBundle.message("diagnostic.error.report.description"))(span, wrap) + link(DiagnosticBundle.message("diagnostic.error.report.proxy.setup"), span, wrap) { HttpConfigurable.editConfigurable(this) } + + label("Username:") + userField(grow, wrap) + + label("Password:") + passwordField(grow, wrap) + + rememberCheckBox(span, wrap) + + link("Create or manage your JetBrains Account", "https://account.jetbrains.com", span, wrap) } return dialog( title = DiagnosticBundle.message("error.report.title"), centerPanel = panel, + preferedFocusComponent = if (credentials?.userName == null) userField else passwordField, project = project, - parent = if (parent.isShowing) parent else null) -} - -class JetBrainsAccountDialog : DialogWrapper(null) { - private val myItnLoginTextField: JTextField? = null - private val myPasswordText: JPasswordField? = null - private val myRememberCheckBox: JCheckBox? = null - - var myMainPanel: JPanel? = null - var mySendingSettingsLabel: JLabel? = null - private val myCreateAccountLabel: JLabel? = null - - override fun getDimensionServiceKey(): String? { - return "#com.intellij.diagnostic.AbstractSendErrorDialog" - } - - override fun getPreferredFocusedComponent(): JComponent? { - return myItnLoginTextField - } - - override fun init() { - contentPane.add(myMainPanel) - - object : ClickListener() { - override fun onClick(e: MouseEvent, clickCount: Int): Boolean { - HttpConfigurable.editConfigurable(myMainPanel) - return true - } - }.installOn(mySendingSettingsLabel!!) - - mySendingSettingsLabel!!.cursor = Cursor(Cursor.HAND_CURSOR) - - val credentials = ErrorReportConfigurable.getCredentials() - val userName = credentials?.userName - myItnLoginTextField!!.text = userName - val password = credentials?.getPasswordAsString() - myPasswordText!!.text = password - // if no user name - never stored and so, defaults to remember. if user name set, but no password, so, previously was stored without password - myRememberCheckBox!!.isSelected = StringUtil.isEmpty(userName) || !StringUtil.isEmpty(password) - - object : ClickListener() { - override fun onClick(e: MouseEvent, clickCount: Int): Boolean { - BrowserUtil.browse("http://account.jetbrains.com") - return true - } - }.installOn(myCreateAccountLabel!!) - myCreateAccountLabel.cursor = Cursor(Cursor.HAND_CURSOR) - - super.init() - } - - override fun doOKAction() { - val userName = myItnLoginTextField!!.text - if (!StringUtil.isEmpty(userName)) { - PasswordSafe.getInstance().set(CredentialAttributes(ErrorReportConfigurable.SERVICE_NAME, userName), - Credentials(userName, if (myRememberCheckBox!!.isSelected) myPasswordText!!.password else null)) + parent = if (parent.isShowing) parent else null) { + val userName = userField.text + if (!userName.isNullOrBlank()) { + PasswordSafe.getInstance().set(CredentialAttributes(ErrorReportConfigurable.SERVICE_NAME, userName), Credentials(userName, if (rememberCheckBox.isSelected) passwordField.password else null)) } - super.doOKAction() } - - override fun createCenterPanel(): JComponent? { - return myMainPanel - } -} +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountForm.form b/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountForm.form deleted file mode 100644 index 8a9f985fc7ba..000000000000 --- a/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountForm.form +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/platform/platform-impl/src/com/intellij/ui/layout/flags.kt b/platform/platform-impl/src/com/intellij/ui/layout/flags.kt new file mode 100644 index 000000000000..8e1a833e5571 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ui/layout/flags.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2000-2016 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. + * You may obtain a copy of the License at + * + * http://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. + */ +package com.intellij.ui.layout + +// http://www.migcalendar.com/miglayout/mavensite/docs/cheatsheet.pdf + +enum class CFlags { +} + +enum class LCFlags { + /** + * Puts the layout in a flow-only mode. + * All components in the flow direction will be put in the same cell and will thus not be aligned with component in other rows/columns. + * For normal horizontal flow this is the same as to say that all component will be put in the first and only column. + */ + noGrid, + + /** + * Puts the layout in vertical flow mode. This means that the next cell is normally below and the next component will be put there instead of to the right. Default is horizontal flow. + */ + flowY, + + /** + * Claims all available space in the container for the columns and/or rows. + * At least one component need to have a "grow" constraint for it to fill the container. + * The space will be divided equal, though honoring "growPriority". + * If no columns/rows has "grow" set the grow weight of the components in the rows/columns will migrate to that row/column. + */ + fill, fillX, fillY, + + lcWrap, + + debug +} + +enum class CCFlags { + /** + * Wrap to the next line/column **after** the component that this constraint belongs to. + */ + wrap, + + /** + * Span cells in both x and y. + */ + span, spanX, spanY, + + split, + + grow, push, pushY, pushX, right, skip +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ui/layout/layout.kt b/platform/platform-impl/src/com/intellij/ui/layout/layout.kt index bfa3e75d2599..339327bcac42 100644 --- a/platform/platform-impl/src/com/intellij/ui/layout/layout.kt +++ b/platform/platform-impl/src/com/intellij/ui/layout/layout.kt @@ -16,6 +16,7 @@ package com.intellij.ui.layout import com.intellij.BundleBase +import com.intellij.ide.BrowserUtil import com.intellij.ui.IdeBorderFactory import com.intellij.ui.components.JBLabel import com.intellij.ui.components.labels.LinkLabel @@ -29,44 +30,6 @@ import java.awt.LayoutManager import java.awt.event.ActionEvent import javax.swing.* -// http://www.migcalendar.com/miglayout/mavensite/docs/cheatsheet.pdf - -enum class LCFlags { - /** - * Puts the layout in a flow-only mode. - * All components in the flow direction will be put in the same cell and will thus not be aligned with component in other rows/columns. - * For normal horizontal flow this is the same as to say that all component will be put in the first and only column. - */ - noGrid, - - /** - * Puts the layout in vertical flow mode. This means that the next cell is normally below and the next component will be put there instead of to the right. Default is horizontal flow. - */ - flowY, - - /** - * Claims all available space in the container for the columns and/or rows. - * At least one component need to have a "grow" constraint for it to fill the container. - * The space will be divided equal, though honoring "growPriority". - * If no columns/rows has "grow" set the grow weight of the components in the rows/columns will migrate to that row/column. - */ - fill, fillX, fillY -} - -enum class CCFlags { - /** - * Wrap to the next line/column **after** the component that this constraint belongs to. - */ - wrap, - - /** - * Span cells in both x and y. - */ - span, - - grow, push, pushY, pushX, right, skip -} - inline fun panel(vararg layoutConstraints: LCFlags, init: Panel.() -> Unit): JPanel { val panel = Panel(MigLayout(c().apply(layoutConstraints))) panel.init() @@ -87,7 +50,15 @@ fun JPanel.titledPanel(title: String, wrappedComponent: Component, vararg constr add(panel, *constraints) } -fun JPanel.label(text: String, vararg constraints: CCFlags, componentStyle: UIUtil.ComponentStyle? = null, fontColor: UIUtil.FontColor? = null, bold: Boolean = false, gapLeft: Int = 0, gapBottom: Int = 0, gapAfter: Int = 0) { +fun JPanel.label(text: String, + vararg constraints: CCFlags, + componentStyle: UIUtil.ComponentStyle? = null, + fontColor: UIUtil.FontColor? = null, + bold: Boolean = false, + gapLeft: Int = 0, + gapBottom: Int = 0, + gapAfter: Int = 0, + split: Int = -1) { val finalText = BundleBase.replaceMnemonicAmpersand(text) val label = if (componentStyle == null && fontColor == null) { JLabel(finalText) @@ -117,11 +88,18 @@ fun JPanel.label(text: String, vararg constraints: CCFlags, componentStyle: UIUt if (gapBottom != 0) { cc().vertical.gapAfter = gapToBoundSize(gapBottom, false) } + if (split != -1) { + cc().split = split + } add(label, _cc) } -fun JPanel.link(text: String, action: () -> Unit) { - add(LinkLabel.create(text, action)) +fun JPanel.link(text: String, vararg constraints: CCFlags, action: () -> Unit) { + add(LinkLabel.create(text, action), constraints.create()) +} + +fun JPanel.link(text: String, url: String, vararg constraints: CCFlags) { + add(LinkLabel.create(text, { BrowserUtil.browse(url) }), constraints.create()) } private fun gapToBoundSize(value: Int, isHorizontal: Boolean): BoundSize { @@ -197,6 +175,10 @@ fun LC.apply(flags: Array): LC { LCFlags.fill -> fill() LCFlags.fillX -> isFillX = true LCFlags.fillY -> isFillY = true + + LCFlags.lcWrap -> wrapAfter = 0 + + LCFlags.debug -> debug() } } return this @@ -214,6 +196,11 @@ fun CC.apply(flags: Array): CC { CCFlags.pushY -> pushY() CCFlags.span -> span() + CCFlags.spanX -> spanX() + CCFlags.spanY -> spanY() + + CCFlags.split -> split() + CCFlags.skip -> skip() } } diff --git a/platform/platform-resources-en/src/messages/DiagnosticBundle.properties b/platform/platform-resources-en/src/messages/DiagnosticBundle.properties index 6989fc38ec71..820c7ef11be8 100644 --- a/platform/platform-resources-en/src/messages/DiagnosticBundle.properties +++ b/platform/platform-resources-en/src/messages/DiagnosticBundle.properties @@ -9,13 +9,10 @@ diagnostic.out.of.memory.currentValue.unknown=Unknown diagnostic.out.of.memory.continue=Continue diagnostic.out.of.memory.dump=Memory Dump diagnostic.error.report.send=&Send -diagnostic.error.report.description=If you would like to get notified when the exceptions you submit are fixed,
please fill in your JetBrains Account login and password. -diagnostic.error.report.proxy.setup=Set up HTTP proxy settings -diagnostic.error.report.login.remember.password.checkbox=&Remember password +diagnostic.error.report.description=If you would like to get notified when the exceptions you submit are fixed,\nplease fill in your JetBrains Account login and password. +diagnostic.error.report.proxy.setup=Set up HTTP proxy settings diagnostic.error.report.login.name=&Username: diagnostic.error.report.login.password=&Password: -diagnostic.error.report.prompt=Error description (optional): -diagnostic.error.report.use.jetbrains.account.button.label=&Use JetBrains Account... diagnostic.error.report.submit.error.anonymously=Submit report anonymously or use JetBrains Account... diagnostic.error.report.submit.report.as=Submit report as {0} diagnostic.error.report.additional.info.label=&Additional information (steps to reproduce, what were you doing when the exception occurred): diff --git a/plugins/settings-repository/src/authForm.kt b/plugins/settings-repository/src/authForm.kt index 66031432d686..15505c8ff7df 100644 --- a/plugins/settings-repository/src/authForm.kt +++ b/plugins/settings-repository/src/authForm.kt @@ -23,6 +23,7 @@ import com.intellij.openapi.ui.dialog import com.intellij.ui.DocumentAdapter import com.intellij.ui.layout.* import com.intellij.ui.layout.CCFlags.* +import com.intellij.ui.layout.CCFlags.wrap import com.intellij.ui.layout.LCFlags.* import com.intellij.ui.noteComponent import com.intellij.util.PathUtilRt @@ -68,7 +69,6 @@ fun showAuthenticationForm(credentials: Credentials?, uri: String, host: String? val authenticationForm = dialog( title = "Settings Repository", - resizable = false, centerPanel = centerPanel, preferedFocusComponent = if (userField.parent == null) passwordField else userField, okActionEnabled = false)