Skip to content

wizard ui improvements #388

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class Client(
}
}

private fun configureProject() {
fun configureProject() {
CheckProjectConfigurationRequest(
getProjectConfigGrpcRequest(project, Testgen.ConfigMode.CHECK),
project,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,6 @@ class UTBotAllProjectSettings(val project: Project) {
}

data class UTBotSettingsModel(
var projectSettings: UTBotProjectStoredSettings.State,
var globalSettings: UTBotProjectIndependentSettings.State,
val projectSettings: UTBotProjectStoredSettings.State,
val globalSettings: UTBotProjectIndependentSettings.State,
)
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import kotlin.properties.Delegates
// allows attaching multiple listeners for value change
class ObservableValue<T>(initialValue: T) {
private val changeListeners: MutableList<(T) -> Unit> = mutableListOf()
var value: T by Delegates.observable(initialValue) { _, _, newVal ->
changeListeners.forEach {
it(newVal)
var value: T by Delegates.observable(initialValue) { _, oldVal, newVal ->
changeListeners.forEach {callback ->
if (oldVal != newVal)
callback(newVal)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ package org.utbot.cpp.clion.plugin.ui.wizard
import com.intellij.ide.wizard.Step
import com.intellij.openapi.ui.DialogPanel
import com.intellij.util.ui.HtmlPanel
import com.intellij.util.ui.UIUtil
import javax.swing.Box
import javax.swing.BoxLayout
import javax.swing.Icon
import javax.swing.JComponent
import javax.swing.JPanel
import java.awt.Component
import java.awt.Dimension
import java.awt.Font

abstract class UTBotBaseWizardStep : Step {
private val panel by lazy { JPanel() }
Expand All @@ -21,18 +24,19 @@ abstract class UTBotBaseWizardStep : Step {
override fun _init() {
if (!isInitialized) {
panel.layout = BoxLayout(panel, BoxLayout.Y_AXIS)
panel.preferredSize = Dimension(800, 400)
panel.preferredSize = Dimension(STEP_WIDTH, STEP_HEIGHT)
panel.minimumSize = panel.preferredSize
createUI()
panel.add(Box.createVerticalGlue())

isInitialized = true
}
}

fun DialogPanel.addToUI() {
alignmentX = Component.LEFT_ALIGNMENT
panel.add(this)
protected fun DialogPanel.addToUI() {
this.maximumSize = Dimension(maximumSize.width, minimumSize.height)
onApplyCallbacks.add { apply() }
addComponentToStep(this)
}

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

override fun getPreferredFocusedComponent(): JComponent? = panel

fun addHtml(htmlResource: String) {
protected fun addHtml(htmlResource: String) {
val text = this.javaClass.classLoader.getResource(htmlResource)?.readText()
?: error("Unable to get resource: $htmlResource")
panel.add(createHtmlComponent(text))
addComponentToStep(createHtmlComponent(text))
}

private fun addComponentToStep(component: JComponent) {
// From BoxLayout docs: all components should have the same alignmentX
component.alignmentX = Component.LEFT_ALIGNMENT
panel.add(component)
}

open fun canProceedToNextStep(): Boolean = true

private fun createHtmlComponent(html: String): JComponent = object : HtmlPanel() {
init {
update()
alignmentX = Component.LEFT_ALIGNMENT
adjustHeightToTextHeight()
adjustHeightToTextHeight(STEP_WIDTH)
}

override fun getBodyFont(): Font = UIUtil.getButtonFont().deriveFont(Font.PLAIN)
override fun getBody() = html

fun adjustHeightToTextHeight() {
// set dummy size, to update preferred
size = Dimension(100, Short.MAX_VALUE.toInt())
fun adjustHeightToTextHeight(parentWidth: Int) {
// to use modelToView2D the size of JTextComponent must be > 0
size = preferredSize
minimumSize = preferredSize
val rectangleWrappingText = modelToView2D(document.length)
preferredSize =
Dimension(parentWidth, rectangleWrappingText.y.toInt() + rectangleWrappingText.height.toInt())
maximumSize = preferredSize
update()
}
}

companion object {
private const val STEP_HEIGHT = 400
private const val STEP_WIDTH = 800
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ import org.utbot.cpp.clion.plugin.ui.wizard.steps.BuildOptionsStep
import org.utbot.cpp.clion.plugin.ui.wizard.steps.ConnectionStep
import org.utbot.cpp.clion.plugin.ui.wizard.steps.IntroStep
import org.utbot.cpp.clion.plugin.ui.wizard.steps.FinalStep
import org.utbot.cpp.clion.plugin.utils.getCurrentClient
import java.awt.event.KeyEvent

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

init {
addStep(IntroStep())
Expand All @@ -40,9 +42,20 @@ class UTBotWizard(private val project: Project) : AbstractWizard<UTBotBaseWizard
fireUTBotSettingsChanged()
}

project.getCurrentClient().configureProject()

super.doOKAction()
}

override fun updateButtons(lastStep: Boolean, canGoNext: Boolean, firstStep: Boolean) {
// set `ok` button's text on last step to `Finish` instead of `Create`
super.updateButtons(lastStep, canGoNext, firstStep)
if (lastStep) {
nextButton.text = "Finish"
nextButton.mnemonic = KeyEvent.getExtendedKeyCodeForChar('F'.code)
}
}

override fun proceedToNextStep() {
if (currentStepObject?.canProceedToNextStep() != false) {
super.proceedToNextStep()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,31 @@ class ConnectionStep(
private val connectionStatus = ObservableValue(ConnectionStatus.Failed)
private val useConnectionDefaults = ObservableValue(false)

inner class ConnectionInfo(val port: Int, val host: String, val remotePath: String) {
constructor(): this(portComponent.number, hostTextField.text, remotePathTextField.text)
fun apply() {
portComponent.number = port
hostTextField.text = host
remotePathTextField.text = remotePath
}
}

private val defaultConnectionInfo = ConnectionInfo(
UTBotAllProjectSettings.DEFAULT_PORT,
UTBotAllProjectSettings.DEFAULT_HOST,
if (isWindows) project.path.toWslFormatIfNeeded()
else UTBotProjectStoredSettings.REMOTE_PATH_VALUE_FOR_LOCAL_SCENARIO
)

private var beforeCheckingBoxConnectionInfo: ConnectionInfo? = null

init {
useConnectionDefaults.addOnChangeListener { newValue ->
if (newValue) {
portComponent.number = UTBotAllProjectSettings.DEFAULT_PORT
hostTextField.text = UTBotAllProjectSettings.DEFAULT_HOST
remotePathTextField.text = if (isWindows) project.path.toWslFormatIfNeeded()
else UTBotProjectStoredSettings.REMOTE_PATH_VALUE_FOR_LOCAL_SCENARIO
beforeCheckingBoxConnectionInfo = ConnectionInfo()
defaultConnectionInfo.apply()
} else {
beforeCheckingBoxConnectionInfo?.apply()
}
}
}
Expand Down Expand Up @@ -143,7 +161,7 @@ class ConnectionStep(
})

val warningMessage: () -> String = {
"⚠️ Warning! Versions are different or not defined:" +
"⚠️ Warning! Versions are different or not defined: " +
"Client: ${ourPluginVersion} Server: ${serverVersion ?: "not defined"}"
}
label(warningMessage()).visibleIf(
Expand Down Expand Up @@ -172,11 +190,11 @@ class ConnectionStep(
.applyToComponent {
remotePathTextField = this
}.enabledIf(object : ComponentPredicate() {
override fun invoke() = !useConnectionDefaults.value
override fun addListener(listener: (Boolean) -> Unit) {
useConnectionDefaults.addOnChangeListener { newValue -> listener(!newValue) }
}
})
override fun invoke() = !useConnectionDefaults.value
override fun addListener(listener: (Boolean) -> Unit) {
useConnectionDefaults.addOnChangeListener { newValue -> listener(!newValue) }
}
})
}
}.addToUI()
}
Expand Down
4 changes: 2 additions & 2 deletions clion-plugin/src/main/resources/media/installation.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<h2>🖥️ Server Installation</h2>
<p> If you are working on remote machine you can start UTBot Server installation
right from here. Otherwise, please do it manually. </p>
<p> In order to learn more about UTBot Server Installation process,
right from here. Otherwise, please do it manually.
In order to learn more about UTBot Server Installation process,
please, refer to the
<a href="https://github.com/UnitTestBot/UTBotCpp/wiki/install-server">installation manual</a>.
</p>