Wizard: rework build system type component so it fits when UI design
This commit is contained in:
+153
-29
@@ -1,51 +1,175 @@
|
|||||||
package org.jetbrains.kotlin.tools.projectWizard.wizard.ui.firstStep
|
package org.jetbrains.kotlin.tools.projectWizard.wizard.ui.firstStep
|
||||||
|
|
||||||
import com.intellij.icons.AllIcons
|
import com.intellij.ide.ui.UISettings
|
||||||
import icons.GradleIcons
|
import com.intellij.openapi.Disposable
|
||||||
import icons.OpenapiIcons
|
import com.intellij.openapi.actionSystem.ex.ActionButtonLook
|
||||||
import org.jetbrains.kotlin.idea.KotlinIcons
|
import com.intellij.ui.layout.panel
|
||||||
|
import com.intellij.util.ui.JBInsets
|
||||||
|
import com.intellij.util.ui.JBUI
|
||||||
|
import com.intellij.util.ui.UIUtil
|
||||||
|
import com.intellij.util.ui.UIUtilities
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.core.Context
|
import org.jetbrains.kotlin.tools.projectWizard.core.Context
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.core.entity.ValidationResult
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.core.entity.isSpecificError
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.DropDownSettingType
|
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.DropDownSettingType
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.SettingReference
|
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.SettingReference
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.reference
|
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.reference
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemPlugin
|
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemPlugin
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemType
|
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemType
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.KotlinPlugin
|
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.KotlinPlugin
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.components.DropDownComponent
|
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.IdeaBasedComponentValidator
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.UIComponentDelegatingSettingComponent
|
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.SettingComponent
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.ValidationIndicator
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
import java.awt.Cursor
|
||||||
|
import java.awt.Dimension
|
||||||
|
import java.awt.Graphics
|
||||||
|
import java.awt.Rectangle
|
||||||
|
import java.awt.event.MouseAdapter
|
||||||
|
import java.awt.event.MouseEvent
|
||||||
|
import javax.swing.JComponent
|
||||||
|
import javax.swing.SwingConstants
|
||||||
|
import javax.swing.SwingUtilities
|
||||||
|
|
||||||
|
|
||||||
class BuildSystemTypeSettingComponent(
|
class BuildSystemTypeSettingComponent(
|
||||||
context: Context
|
context: Context
|
||||||
) : UIComponentDelegatingSettingComponent<BuildSystemType, DropDownSettingType<BuildSystemType>>(
|
) : SettingComponent<BuildSystemType, DropDownSettingType<BuildSystemType>>(
|
||||||
BuildSystemPlugin::type.reference,
|
BuildSystemPlugin::type.reference,
|
||||||
context
|
context
|
||||||
) {
|
), Disposable {
|
||||||
override val uiComponent: DropDownComponent<BuildSystemType> = DropDownComponent(
|
private val buttons = setting.type.values.map(::BuildSystemChooseButton)
|
||||||
context,
|
override val component = panel {
|
||||||
setting.type.values,
|
row {
|
||||||
labelText = null,
|
buttons.forEach { button -> button(growX) }
|
||||||
filter = { value -> read { setting.type.filter(this, reference, value) } },
|
}
|
||||||
validator = setting.validator,
|
}
|
||||||
iconProvider = BuildSystemType::icon,
|
|
||||||
onValueUpdate = { value = it }
|
|
||||||
).asSubComponent()
|
|
||||||
|
|
||||||
|
override val validationIndicator: ValidationIndicator = IdeaBasedComponentValidator(this, component)
|
||||||
|
|
||||||
|
override fun onInit() {
|
||||||
|
super.onInit()
|
||||||
|
updateButtonsValidationState()
|
||||||
|
updateButtons()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun navigateTo(error: ValidationResult.ValidationError) {
|
||||||
|
if (validationIndicator.validationState.isSpecificError(error)) {
|
||||||
|
component.requestFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onValueUpdated(reference: SettingReference<*, *>?) {
|
override fun onValueUpdated(reference: SettingReference<*, *>?) {
|
||||||
super.onValueUpdated(reference)
|
super.onValueUpdated(reference)
|
||||||
if (reference == KotlinPlugin::projectKind.reference) {
|
if (reference == BuildSystemPlugin::type.reference) {
|
||||||
uiComponent.component.updateUI()
|
updateButtons()
|
||||||
}
|
}
|
||||||
value?.let(uiComponent::validate)
|
if (reference == KotlinPlugin::projectKind.reference) {
|
||||||
|
updateButtonsValidationState()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateButtonsValidationState() {
|
||||||
|
buttons.forEach(BuildSystemChooseButton::updateValidationState)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun validateBuildSystem(buildSystem: BuildSystemType) = read {
|
||||||
|
setting.validator.validate(this, buildSystem)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateButtons() {
|
||||||
|
buttons.forEach(BuildSystemChooseButton::updateSelectedBuildSystem)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dispose() {}
|
||||||
|
|
||||||
|
private inner class BuildSystemChooseButton(private val buildSystemType: BuildSystemType) : JComponent() {
|
||||||
|
private val look = ActionButtonLook.SYSTEM_LOOK
|
||||||
|
|
||||||
|
init {
|
||||||
|
font = UIUtil.getLabelFont()
|
||||||
|
preferredSize = Dimension(preferredSize.width, BUTTON_HEIGHT)
|
||||||
|
minimumSize = Dimension(minimumSize.width, BUTTON_HEIGHT)
|
||||||
|
cursor = Cursor(Cursor.HAND_CURSOR)
|
||||||
|
addMouseListener(object : MouseAdapter() {
|
||||||
|
override fun mouseClicked(e: MouseEvent?) = modify {
|
||||||
|
if (isValidBuildSystem) {
|
||||||
|
BuildSystemPlugin::type.reference.setValue(buildSystemType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseEntered(e: MouseEvent?) {
|
||||||
|
hovered = true
|
||||||
|
repaint()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseExited(e: MouseEvent?) {
|
||||||
|
hovered = false
|
||||||
|
repaint()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateSelectedBuildSystem() {
|
||||||
|
val currentBuildSystem = read { BuildSystemPlugin::type.settingValue }
|
||||||
|
selected = currentBuildSystem == buildSystemType
|
||||||
|
repaint()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateValidationState() {
|
||||||
|
val validationResult = validateBuildSystem(buildSystemType)
|
||||||
|
isValidBuildSystem = validationResult.isOk
|
||||||
|
cursor = Cursor(if (isValidBuildSystem) Cursor.HAND_CURSOR else Cursor.DEFAULT_CURSOR)
|
||||||
|
toolTipText = validationResult.safeAs<ValidationResult.ValidationError>()
|
||||||
|
?.messages
|
||||||
|
?.firstOrNull()
|
||||||
|
?.takeUnless { isSelectedAndInvalid }
|
||||||
|
repaint()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// mostly copied from com.intellij.openapi.actionSystem.impl.ActionButtonWithText.paintComponent
|
||||||
|
override fun paintComponent(g: Graphics) {
|
||||||
|
UISettings.setupAntialiasing(g)
|
||||||
|
|
||||||
|
val fm = getFontMetrics(font)
|
||||||
|
val viewRect = Rectangle(size)
|
||||||
|
JBInsets.removeFrom(viewRect, insets)
|
||||||
|
|
||||||
|
val iconRect = Rectangle()
|
||||||
|
val textRect = Rectangle()
|
||||||
|
val text = SwingUtilities.layoutCompoundLabel(
|
||||||
|
this, fm, buildSystemType.text, null,
|
||||||
|
SwingConstants.CENTER, SwingConstants.CENTER,
|
||||||
|
SwingConstants.CENTER, SwingConstants.TRAILING,
|
||||||
|
viewRect, iconRect, textRect, 0
|
||||||
|
)
|
||||||
|
|
||||||
|
look.paintLookBackground(g, viewRect, bgColor())
|
||||||
|
|
||||||
|
g.color = if (isValidBuildSystem) foreground else UIUtil.getInactiveTextColor()
|
||||||
|
UIUtilities.drawStringUnderlineCharAt(
|
||||||
|
this, g, text, -1,
|
||||||
|
textRect.x, textRect.y + fm.ascent
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun bgColor() = when {
|
||||||
|
selected -> JBUI.CurrentTheme.ActionButton.pressedBackground()
|
||||||
|
hovered -> JBUI.CurrentTheme.ActionButton.hoverBackground()
|
||||||
|
else -> background
|
||||||
|
}
|
||||||
|
|
||||||
|
private var selected: Boolean = false
|
||||||
|
private var hovered: Boolean = false
|
||||||
|
private var isValidBuildSystem: Boolean = true
|
||||||
|
|
||||||
|
private val isSelectedAndInvalid
|
||||||
|
get() = selected && !isValidBuildSystem
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val BUTTON_HEIGHT = 25
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
private val BuildSystemType.icon
|
|
||||||
get() = when (this) {
|
|
||||||
BuildSystemType.GradleKotlinDsl -> KotlinIcons.GRADLE_SCRIPT
|
|
||||||
BuildSystemType.GradleGroovyDsl -> GradleIcons.Gradle
|
|
||||||
BuildSystemType.Maven -> OpenapiIcons.RepositoryLibraryLogo
|
|
||||||
BuildSystemType.Jps -> AllIcons.Nodes.Module
|
|
||||||
}
|
|
||||||
+5
@@ -18,15 +18,20 @@ import javax.swing.JPanel
|
|||||||
|
|
||||||
interface ValidationIndicator {
|
interface ValidationIndicator {
|
||||||
fun updateValidationState(newState: ValidationResult)
|
fun updateValidationState(newState: ValidationResult)
|
||||||
|
val validationState: ValidationResult
|
||||||
}
|
}
|
||||||
|
|
||||||
class IdeaBasedComponentValidator(
|
class IdeaBasedComponentValidator(
|
||||||
parentDisposable: Disposable,
|
parentDisposable: Disposable,
|
||||||
private val jComponent: JComponent
|
private val jComponent: JComponent
|
||||||
) : ValidationIndicator {
|
) : ValidationIndicator {
|
||||||
|
override var validationState: ValidationResult = ValidationResult.OK
|
||||||
|
private set
|
||||||
|
|
||||||
private val validator = ComponentValidator(parentDisposable).installOn(jComponent)
|
private val validator = ComponentValidator(parentDisposable).installOn(jComponent)
|
||||||
|
|
||||||
override fun updateValidationState(newState: ValidationResult) {
|
override fun updateValidationState(newState: ValidationResult) {
|
||||||
|
validationState = newState
|
||||||
validator.updateInfo(
|
validator.updateInfo(
|
||||||
newState.safeAs<ValidationResult.ValidationError>()
|
newState.safeAs<ValidationResult.ValidationError>()
|
||||||
?.messages
|
?.messages
|
||||||
|
|||||||
Reference in New Issue
Block a user