From 81bd3606e1e98905ab37910a5730695aa9a4200e Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Thu, 22 Mar 2018 13:06:24 +0100 Subject: [PATCH] Kotlin UI DSL: * Top and bottom paddings for note row (explanation text) now conforms to our guideline (bigger than before). * For all JPasswordField new automatic rule is used: width `250`. If you have `growPolicy = GrowPolicy.SHORT_TEXT` for password fields, now you can remove this unnecessary flag. * grow policy SHORT_TEXT changed: maxWidth now 250 instead of 210. Kotlin UI DSL is covered by tests, so, in case of regressions, please contact me to add missed test case. Currently, Kotlin UI DSL (`noteRow`) doesn't check that your text has a correct width, it is your responsibility to insert `\n` if need. --- .../src/PasswordSafeConfigurable.kt | 2 +- .../diagnostic/JetBrainsAccountDialog.kt | 4 +- .../src/com/intellij/ui/layout/layoutImpl.kt | 3 +- .../ui/layout/migLayout/MigLayoutBuilder.kt | 2 - .../ui/layout/note row in the dialog.yml | 24 +++++ .../intellij/ui/layout/MigLayoutTestApp.kt | 95 +++++++++---------- .../com/intellij/ui/layout/UiDslTest.kt | 15 ++- 7 files changed, 87 insertions(+), 58 deletions(-) create mode 100644 platform/platform-tests/testData/ui/layout/note row in the dialog.yml diff --git a/platform/credential-store/src/PasswordSafeConfigurable.kt b/platform/credential-store/src/PasswordSafeConfigurable.kt index f1c2cf2ef97e..199c6289eddb 100644 --- a/platform/credential-store/src/PasswordSafeConfigurable.kt +++ b/platform/credential-store/src/PasswordSafeConfigurable.kt @@ -201,7 +201,7 @@ internal class PasswordSafeConfigurableUi : ConfigurableUi ) } row("Master Password:") { - keePassMasterPassword(growPolicy = GrowPolicy.SHORT_TEXT) + keePassMasterPassword() } if (!SystemInfo.isWindows) { row { hint("Stored using weak encryption. It is recommended to store on encrypted volume for additional security.") } diff --git a/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.kt b/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.kt index 80f446eb0883..1c767738b660 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.kt +++ b/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.kt @@ -26,8 +26,8 @@ fun showJetBrainsAccountDialog(parent: Component, project: Project? = null): Dia val rememberCheckBox = CheckBox(CommonBundle.message("checkbox.remember.password"), selected = credentials?.userName == null || !credentials.password.isNullOrEmpty()) val panel = panel { - noteRow("Login to JetBrains Account to get notified when the submitted\nexceptions are fixed.") - row("Username:") { userField() } + noteRow("Login to JetBrains Account to get notified\nwhen the submitted exceptions are fixed.") + row("Username:") { userField(growPolicy = GrowPolicy.SHORT_TEXT) } row("Password:") { passwordField() } row { rememberCheckBox() diff --git a/platform/platform-impl/src/com/intellij/ui/layout/layoutImpl.kt b/platform/platform-impl/src/com/intellij/ui/layout/layoutImpl.kt index daadc24214ee..b001ef1e9e13 100644 --- a/platform/platform-impl/src/com/intellij/ui/layout/layoutImpl.kt +++ b/platform/platform-impl/src/com/intellij/ui/layout/layoutImpl.kt @@ -12,7 +12,8 @@ import javax.swing.JLabel internal const val HORIZONTAL_GAP = 10 internal const val VERTICAL_GAP = 5 -fun createLayoutBuilder() = LayoutBuilder(MigLayoutBuilder()) +@PublishedApi +internal fun createLayoutBuilder() = LayoutBuilder(MigLayoutBuilder()) interface LayoutBuilderImpl { fun newRow(label: JLabel? = null, buttonGroup: ButtonGroup? = null, separated: Boolean = false): Row diff --git a/platform/platform-impl/src/com/intellij/ui/layout/migLayout/MigLayoutBuilder.kt b/platform/platform-impl/src/com/intellij/ui/layout/migLayout/MigLayoutBuilder.kt index 3ca95351529c..6a6a5eab5598 100644 --- a/platform/platform-impl/src/com/intellij/ui/layout/migLayout/MigLayoutBuilder.kt +++ b/platform/platform-impl/src/com/intellij/ui/layout/migLayout/MigLayoutBuilder.kt @@ -214,8 +214,6 @@ private fun addGrowIfNeed(cc: CC, component: Component) { component is JPasswordField -> { applyGrowPolicy(cc, GrowPolicy.SHORT_TEXT) - cc.grow(0f) - cc.width("210!") } component is JTextComponent || component is SeparatorComponent || component is ComponentWithBrowseButton<*> -> { diff --git a/platform/platform-tests/testData/ui/layout/note row in the dialog.yml b/platform/platform-tests/testData/ui/layout/note row in the dialog.yml new file mode 100644 index 000000000000..0850c16fb714 --- /dev/null +++ b/platform/platform-tests/testData/ui/layout/note row in the dialog.yml @@ -0,0 +1,24 @@ +rowConstraints: '' +columnConstraints: + count: 2.0 + constraints: + - {} + - {grow: 100.0} +componentConstrains: + 'JLabel #0': + spanX: 2097051.0 + wrap: true + vertical: + gapBefore: + min: {value: 5.0, unit: 2.0} + preferred: {value: 5.0, unit: 2.0} + gapAfter: + min: {value: 10.0, unit: 2.0} + preferred: {value: 10.0, unit: 2.0} + 'JLabel #1': {} + 'JPasswordField #2': + wrap: true + horizontal: + size: + preferred: {value: 250.0} + 'JCheckBox #3': {skip: 1.0, spanX: 2097051.0, wrap: true} diff --git a/platform/platform-tests/testSrc/com/intellij/ui/layout/MigLayoutTestApp.kt b/platform/platform-tests/testSrc/com/intellij/ui/layout/MigLayoutTestApp.kt index d86657293345..d02686e8229c 100644 --- a/platform/platform-tests/testSrc/com/intellij/ui/layout/MigLayoutTestApp.kt +++ b/platform/platform-tests/testSrc/com/intellij/ui/layout/MigLayoutTestApp.kt @@ -1,69 +1,62 @@ // 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.ui.layout -import com.intellij.openapi.actionSystem.AnAction -import com.intellij.openapi.actionSystem.AnActionEvent -import com.intellij.ui.components.JBPasswordField -import com.intellij.ui.components.RadioButton -import net.miginfocom.layout.LayoutUtil -import net.miginfocom.swing.MigLayout -import java.awt.BorderLayout -import java.awt.Color -import java.awt.Dimension -import javax.swing.JFrame +import com.intellij.CommonBundle +import com.intellij.ide.BrowserUtil +import com.intellij.testFramework.runInEdtAndWait +import com.intellij.ui.components.CheckBox +import com.intellij.ui.components.dialog +import javax.swing.JPasswordField import javax.swing.JTextField object MigLayoutTestApp { @JvmStatic fun main(args: Array) { - LayoutUtil.setGlobalDebugMillis(1000) +// LayoutUtil.setGlobalDebugMillis(1000) - val panel = panel { - row { label("Save passwords:") } + runInEdtAndWait { + val passwordField = JPasswordField() +// val panel = panel { +// noteRow("Profiler requires access to the kernel-level API.\nEnter the sudo password to allow this. ") +// row("Sudo password:") { passwordField() } +// row { CheckBox(CommonBundle.message("checkbox.remember.password"), true)() } +// } - buttonGroup { + val panel = panel { + noteRow("Login to JetBrains Account to get notified\nwhen the submitted exceptions are fixed.") + row("Username:") { JTextField()(growPolicy = GrowPolicy.SHORT_TEXT) } + row("Password:") { passwordField() } row { - RadioButton("In KeePass")() - row("Database:") { - JTextField()() - gearButton( - object : AnAction("Clear") { - override fun actionPerformed(event: AnActionEvent) { - } - }, - object : AnAction("Import") { - override fun actionPerformed(event: AnActionEvent) { - } - } - ) - } - row("Master Password:") { - JBPasswordField()(growPolicy = GrowPolicy.SHORT_TEXT) - } - row { - hint("Stored using weak encryption.") + CheckBox(CommonBundle.message("checkbox.remember.password"))() + right { + link("Forgot password?") { + BrowserUtil.browse("https://account.jetbrains.com/forgot-password?username=") + } } } - - row { - RadioButton("Do not save, forget passwords after restart")() - } - row { - hint("Existing KeePass file will be removed.") - } + noteRow("""Do not have an account? Sign Up""") } + dialog( + title = "Access Required", + panel = panel, + focusedComponent = passwordField, + okActionEnabled = false + ) { + return@dialog null + } + .showAndGet() } - val frame = JFrame() - frame.defaultCloseOperation = JFrame.EXIT_ON_CLOSE - frame.contentPane.add(panel, BorderLayout.CENTER) - frame.contentPane.background = Color.WHITE - frame.background = Color.WHITE - frame.pack() - frame.setLocationRelativeTo(null) - frame.minimumSize = Dimension(512, 256) - frame.isVisible = true - - System.out.println(configurationToJson(panel, panel.layout as MigLayout, false)) +// val frame = JFrame() +// frame.defaultCloseOperation = JFrame.EXIT_ON_CLOSE +// frame.contentPane.add(panel, BorderLayout.CENTER) +// frame.contentPane.background = Color.WHITE +// frame.background = Color.WHITE +// frame.pack() +// frame.setLocationRelativeTo(null) +// frame.minimumSize = Dimension(512, 256) +// frame.isVisible = true +// +// System.out.println(configurationToJson(panel, panel.layout as MigLayout, false)) } } \ No newline at end of file diff --git a/platform/platform-tests/testSrc/com/intellij/ui/layout/UiDslTest.kt b/platform/platform-tests/testSrc/com/intellij/ui/layout/UiDslTest.kt index ee2fc74bef2d..8ef983103ea7 100644 --- a/platform/platform-tests/testSrc/com/intellij/ui/layout/UiDslTest.kt +++ b/platform/platform-tests/testSrc/com/intellij/ui/layout/UiDslTest.kt @@ -1,9 +1,11 @@ // 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.ui.layout +import com.intellij.CommonBundle import com.intellij.openapi.application.invokeAndWaitIfNeed import com.intellij.testFramework.PlatformTestUtil import com.intellij.testFramework.UsefulTestCase +import com.intellij.testFramework.assertions.Assertions import com.intellij.ui.components.CheckBox import com.intellij.ui.components.JBPasswordField import com.intellij.ui.components.RadioButton @@ -30,6 +32,7 @@ import java.util.concurrent.Callable import javax.imageio.ImageIO import javax.swing.JFrame import javax.swing.JPanel +import javax.swing.JPasswordField import javax.swing.JTextField import kotlin.properties.Delegates @@ -99,6 +102,16 @@ class UiDslTest { }, "[0, 0, 145, 23], [165, 0, 347, 23], [0, 28, 145, 26], [165, 28, 347, 26]") } + @Test + fun `note row in the dialog`() { + val passwordField = JPasswordField() + doTest(panel { + noteRow("Profiler requires access to the kernel-level API. Enter the sudo password to allow this. ") + row("Sudo password:") { passwordField() } + row { CheckBox(CommonBundle.message("checkbox.remember.password"), true)() } + }, "[0, 0, 544, 31], [0, 36, 99, 26], [119, 36, 425, 26], [119, 67, 425, 23]") + } + private fun doTest(panel: JPanel, expectedLocations: String) { val frame = GuiActionRunner.execute(Callable { LayoutUtil.setGlobalDebugMillis(1000) @@ -124,7 +137,7 @@ class UiDslTest { try { val expectedLayoutDataFile = Paths.get(PlatformTestUtil.getPlatformTestDataPath(), "ui", "layout", "$imageName.yml") if (expectedLayoutDataFile.exists()) { - com.intellij.testFramework.assertions.Assertions.assertThat(actualLayoutJson).isEqualTo(expectedLayoutDataFile) + Assertions.assertThat(actualLayoutJson).isEqualTo(expectedLayoutDataFile) } else { expectedLayoutDataFile.write(actualLayoutJson)