Skip to content

Commit 70703b6

Browse files
authored
clion plugin: wizard ui improvements (#388)
* fix spacing between components * Restore typed options after unchecking check box * do configure project after finishing wizard * Set last button text to 'Finish' * fix: unfinished wizard modifies settings
1 parent 4cec911 commit 70703b6

File tree

7 files changed

+79
-31
lines changed

7 files changed

+79
-31
lines changed

clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/client/Client.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ class Client(
9090
}
9191
}
9292

93-
private fun configureProject() {
93+
fun configureProject() {
9494
CheckProjectConfigurationRequest(
9595
getProjectConfigGrpcRequest(project, Testgen.ConfigMode.CHECK),
9696
project,

clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/settings/UTBotAllProjectSettings.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,6 @@ class UTBotAllProjectSettings(val project: Project) {
6969
}
7070

7171
data class UTBotSettingsModel(
72-
var projectSettings: UTBotProjectStoredSettings.State,
73-
var globalSettings: UTBotProjectIndependentSettings.State,
72+
val projectSettings: UTBotProjectStoredSettings.State,
73+
val globalSettings: UTBotProjectIndependentSettings.State,
7474
)

clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/ObservableValue.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ import kotlin.properties.Delegates
55
// allows attaching multiple listeners for value change
66
class ObservableValue<T>(initialValue: T) {
77
private val changeListeners: MutableList<(T) -> Unit> = mutableListOf()
8-
var value: T by Delegates.observable(initialValue) { _, _, newVal ->
9-
changeListeners.forEach {
10-
it(newVal)
8+
var value: T by Delegates.observable(initialValue) { _, oldVal, newVal ->
9+
changeListeners.forEach {callback ->
10+
if (oldVal != newVal)
11+
callback(newVal)
1112
}
1213
}
1314

clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/wizard/UTBotBaseWizardStep.kt

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@ package org.utbot.cpp.clion.plugin.ui.wizard
33
import com.intellij.ide.wizard.Step
44
import com.intellij.openapi.ui.DialogPanel
55
import com.intellij.util.ui.HtmlPanel
6+
import com.intellij.util.ui.UIUtil
7+
import javax.swing.Box
68
import javax.swing.BoxLayout
79
import javax.swing.Icon
810
import javax.swing.JComponent
911
import javax.swing.JPanel
1012
import java.awt.Component
1113
import java.awt.Dimension
14+
import java.awt.Font
1215

1316
abstract class UTBotBaseWizardStep : Step {
1417
private val panel by lazy { JPanel() }
@@ -21,18 +24,19 @@ abstract class UTBotBaseWizardStep : Step {
2124
override fun _init() {
2225
if (!isInitialized) {
2326
panel.layout = BoxLayout(panel, BoxLayout.Y_AXIS)
24-
panel.preferredSize = Dimension(800, 400)
27+
panel.preferredSize = Dimension(STEP_WIDTH, STEP_HEIGHT)
2528
panel.minimumSize = panel.preferredSize
2629
createUI()
30+
panel.add(Box.createVerticalGlue())
2731

2832
isInitialized = true
2933
}
3034
}
3135

32-
fun DialogPanel.addToUI() {
33-
alignmentX = Component.LEFT_ALIGNMENT
34-
panel.add(this)
36+
protected fun DialogPanel.addToUI() {
37+
this.maximumSize = Dimension(maximumSize.width, minimumSize.height)
3538
onApplyCallbacks.add { apply() }
39+
addComponentToStep(this)
3640
}
3741

3842
override fun _commit(finishChosen: Boolean) = onApplyCallbacks.forEach { it.invoke() }
@@ -44,30 +48,42 @@ abstract class UTBotBaseWizardStep : Step {
4448

4549
override fun getPreferredFocusedComponent(): JComponent? = panel
4650

47-
fun addHtml(htmlResource: String) {
51+
protected fun addHtml(htmlResource: String) {
4852
val text = this.javaClass.classLoader.getResource(htmlResource)?.readText()
4953
?: error("Unable to get resource: $htmlResource")
50-
panel.add(createHtmlComponent(text))
54+
addComponentToStep(createHtmlComponent(text))
55+
}
56+
57+
private fun addComponentToStep(component: JComponent) {
58+
// From BoxLayout docs: all components should have the same alignmentX
59+
component.alignmentX = Component.LEFT_ALIGNMENT
60+
panel.add(component)
5161
}
5262

5363
open fun canProceedToNextStep(): Boolean = true
5464

5565
private fun createHtmlComponent(html: String): JComponent = object : HtmlPanel() {
5666
init {
5767
update()
58-
alignmentX = Component.LEFT_ALIGNMENT
59-
adjustHeightToTextHeight()
68+
adjustHeightToTextHeight(STEP_WIDTH)
6069
}
6170

71+
override fun getBodyFont(): Font = UIUtil.getButtonFont().deriveFont(Font.PLAIN)
6272
override fun getBody() = html
6373

64-
fun adjustHeightToTextHeight() {
65-
// set dummy size, to update preferred
66-
size = Dimension(100, Short.MAX_VALUE.toInt())
74+
fun adjustHeightToTextHeight(parentWidth: Int) {
75+
// to use modelToView2D the size of JTextComponent must be > 0
6776
size = preferredSize
68-
minimumSize = preferredSize
77+
val rectangleWrappingText = modelToView2D(document.length)
78+
preferredSize =
79+
Dimension(parentWidth, rectangleWrappingText.y.toInt() + rectangleWrappingText.height.toInt())
6980
maximumSize = preferredSize
7081
update()
7182
}
7283
}
84+
85+
companion object {
86+
private const val STEP_HEIGHT = 400
87+
private const val STEP_WIDTH = 800
88+
}
7389
}

clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/wizard/UTBotWizard.kt

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ import org.utbot.cpp.clion.plugin.ui.wizard.steps.BuildOptionsStep
1212
import org.utbot.cpp.clion.plugin.ui.wizard.steps.ConnectionStep
1313
import org.utbot.cpp.clion.plugin.ui.wizard.steps.IntroStep
1414
import org.utbot.cpp.clion.plugin.ui.wizard.steps.FinalStep
15+
import org.utbot.cpp.clion.plugin.utils.getCurrentClient
16+
import java.awt.event.KeyEvent
1517

1618
class UTBotWizard(private val project: Project) : AbstractWizard<UTBotBaseWizardStep>("UTBot: Quickstart", project) {
1719
// copy of settings to make changes during wizard steps
18-
private val mySettingsModel = UTBotSettingsModel(project.settings.storedSettings, projectIndependentSettings)
20+
private val mySettingsModel = UTBotSettingsModel(project.settings.storedSettings.copy(), projectIndependentSettings.copy())
1921

2022
init {
2123
addStep(IntroStep())
@@ -40,9 +42,20 @@ class UTBotWizard(private val project: Project) : AbstractWizard<UTBotBaseWizard
4042
fireUTBotSettingsChanged()
4143
}
4244

45+
project.getCurrentClient().configureProject()
46+
4347
super.doOKAction()
4448
}
4549

50+
override fun updateButtons(lastStep: Boolean, canGoNext: Boolean, firstStep: Boolean) {
51+
// set `ok` button's text on last step to `Finish` instead of `Create`
52+
super.updateButtons(lastStep, canGoNext, firstStep)
53+
if (lastStep) {
54+
nextButton.text = "Finish"
55+
nextButton.mnemonic = KeyEvent.getExtendedKeyCodeForChar('F'.code)
56+
}
57+
}
58+
4659
override fun proceedToNextStep() {
4760
if (currentStepObject?.canProceedToNextStep() != false) {
4861
super.proceedToNextStep()

clion-plugin/src/main/kotlin/org/utbot/cpp/clion/plugin/ui/wizard/steps/ConnectionStep.kt

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,31 @@ class ConnectionStep(
5656
private val connectionStatus = ObservableValue(ConnectionStatus.Failed)
5757
private val useConnectionDefaults = ObservableValue(false)
5858

59+
inner class ConnectionInfo(val port: Int, val host: String, val remotePath: String) {
60+
constructor(): this(portComponent.number, hostTextField.text, remotePathTextField.text)
61+
fun apply() {
62+
portComponent.number = port
63+
hostTextField.text = host
64+
remotePathTextField.text = remotePath
65+
}
66+
}
67+
68+
private val defaultConnectionInfo = ConnectionInfo(
69+
UTBotAllProjectSettings.DEFAULT_PORT,
70+
UTBotAllProjectSettings.DEFAULT_HOST,
71+
if (isWindows) project.path.toWslFormatIfNeeded()
72+
else UTBotProjectStoredSettings.REMOTE_PATH_VALUE_FOR_LOCAL_SCENARIO
73+
)
74+
75+
private var beforeCheckingBoxConnectionInfo: ConnectionInfo? = null
76+
5977
init {
6078
useConnectionDefaults.addOnChangeListener { newValue ->
6179
if (newValue) {
62-
portComponent.number = UTBotAllProjectSettings.DEFAULT_PORT
63-
hostTextField.text = UTBotAllProjectSettings.DEFAULT_HOST
64-
remotePathTextField.text = if (isWindows) project.path.toWslFormatIfNeeded()
65-
else UTBotProjectStoredSettings.REMOTE_PATH_VALUE_FOR_LOCAL_SCENARIO
80+
beforeCheckingBoxConnectionInfo = ConnectionInfo()
81+
defaultConnectionInfo.apply()
82+
} else {
83+
beforeCheckingBoxConnectionInfo?.apply()
6684
}
6785
}
6886
}
@@ -143,7 +161,7 @@ class ConnectionStep(
143161
})
144162

145163
val warningMessage: () -> String = {
146-
"⚠️ Warning! Versions are different or not defined:" +
164+
"⚠️ Warning! Versions are different or not defined: " +
147165
"Client: ${ourPluginVersion} Server: ${serverVersion ?: "not defined"}"
148166
}
149167
label(warningMessage()).visibleIf(
@@ -172,11 +190,11 @@ class ConnectionStep(
172190
.applyToComponent {
173191
remotePathTextField = this
174192
}.enabledIf(object : ComponentPredicate() {
175-
override fun invoke() = !useConnectionDefaults.value
176-
override fun addListener(listener: (Boolean) -> Unit) {
177-
useConnectionDefaults.addOnChangeListener { newValue -> listener(!newValue) }
178-
}
179-
})
193+
override fun invoke() = !useConnectionDefaults.value
194+
override fun addListener(listener: (Boolean) -> Unit) {
195+
useConnectionDefaults.addOnChangeListener { newValue -> listener(!newValue) }
196+
}
197+
})
180198
}
181199
}.addToUI()
182200
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<h2>🖥️ Server Installation</h2>
22
<p> If you are working on remote machine you can start UTBot Server installation
3-
right from here. Otherwise, please do it manually. </p>
4-
<p> In order to learn more about UTBot Server Installation process,
3+
right from here. Otherwise, please do it manually.
4+
In order to learn more about UTBot Server Installation process,
55
please, refer to the
66
<a href="https://github.com/UnitTestBot/UTBotCpp/wiki/install-server">installation manual</a>.
77
</p>

0 commit comments

Comments
 (0)