Skip to content

Commit

Permalink
Support widget themes
Browse files Browse the repository at this point in the history
  • Loading branch information
lippfi committed Jan 23, 2024
1 parent 0e69168 commit fb75508
Show file tree
Hide file tree
Showing 5 changed files with 314 additions and 240 deletions.
271 changes: 168 additions & 103 deletions src/main/java/com/maddyhome/idea/vim/ui/widgets/mode/ModeWidgetPopup.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,25 @@ import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.ui.DialogPanel
import com.intellij.openapi.ui.popup.JBPopup
import com.intellij.openapi.ui.popup.JBPopupFactory
import com.intellij.ui.components.JBCheckBox
import com.intellij.ui.components.JBScrollPane
import com.intellij.ui.components.JBTabbedPane
import com.intellij.ui.content.ContentFactory
import com.intellij.ui.dsl.builder.Cell
import com.intellij.ui.dsl.builder.RowLayout
import com.intellij.ui.dsl.builder.TopGap
import com.intellij.ui.dsl.builder.bindItem
import com.intellij.ui.dsl.builder.bindSelected
import com.intellij.ui.dsl.builder.bindText
import com.intellij.ui.dsl.builder.panel
import com.intellij.ui.dsl.builder.selected
import com.intellij.ui.dsl.builder.toNullableProperty
import com.intellij.ui.layout.not
import com.intellij.util.Alarm
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.helper.MessageHelper
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString
import com.maddyhome.idea.vim.vimscript.model.datatypes.asVimInt
import java.awt.BorderLayout
import java.awt.Dimension
import java.awt.FlowLayout
Expand All @@ -35,7 +44,6 @@ import javax.swing.JPanel
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty


public class ModeWidgetPopup : AnAction() {
public override fun actionPerformed(e: AnActionEvent) {
val project = e.project ?: return
Expand Down Expand Up @@ -64,7 +72,7 @@ public class ModeWidgetPopup : AnAction() {
val darkThemeSettings = createPanel(getWidgetThemeColors(false))
tabbedPane.addTab(MessageHelper.getMessage("widget.mode.popup.tab.light"), lightThemeSettings.addScrollPane())
tabbedPane.addTab(MessageHelper.getMessage("widget.mode.popup.tab.dark"), darkThemeSettings.addScrollPane())
tabbedPane.preferredSize = Dimension(300, 600)
tabbedPane.preferredSize = Dimension(300, 300)
for (i in 0 until tabbedPane.tabCount) {
val label = JLabel(tabbedPane.getTitleAt(i), JLabel.CENTER)
label.preferredSize = Dimension(126, tabbedPane.getTabComponentAt(i).preferredSize.height)
Expand All @@ -77,6 +85,7 @@ public class ModeWidgetPopup : AnAction() {
val popup = JBPopupFactory.getInstance()
.createComponentPopupBuilder(popupContent, popupContent)
.setTitle(MessageHelper.getMessage("widget.mode.popup.title"))
.setResizable(true)
.setMovable(true)
.setRequestFocus(true)
.setCancelOnClickOutside(false)
Expand Down Expand Up @@ -110,6 +119,8 @@ public class ModeWidgetPopup : AnAction() {
private fun getWidgetThemeColors(isLight: Boolean): ModeColors {
val keyPostfix = if (isLight) "_light" else "_dark"
return ModeColors(
"widget_mode_is_full_customization$keyPostfix",
"widget_mode_theme$keyPostfix",
"widget_mode_normal_background$keyPostfix",
"widget_mode_normal_foreground$keyPostfix",
"widget_mode_insert_background$keyPostfix",
Expand All @@ -135,121 +146,134 @@ public class ModeWidgetPopup : AnAction() {

private fun createPanel(modeColors: ModeColors): DialogPanel {
val panel = panel {
row { text(MessageHelper.getMessage("widget.mode.popup.color.instruction")) }

group(MessageHelper.getMessage("widget.mode.popup.group.normal.title")) {
row {
label(MessageHelper.getMessage("widget.mode.popup.field.background"))
textField().bindText(modeColors::normalBg)
}.layout(RowLayout.PARENT_GRID)
row {
label(MessageHelper.getMessage("widget.mode.popup.field.foreground"))
textField().bindText(modeColors::normalFg)
}.layout(RowLayout.PARENT_GRID)
lateinit var advancedSettings: Cell<JBCheckBox>
row {
advancedSettings = checkBox(MessageHelper.getMessage("widget.mode.popup.field.advanced.settings")).bindSelected(modeColors::isFullCustomization)
}

group(MessageHelper.getMessage("widget.mode.popup.group.insert.title")) {
row {
label(MessageHelper.getMessage("widget.mode.popup.field.background"))
textField().bindText(modeColors::insertBg)
}.layout(RowLayout.PARENT_GRID)
group {
row {
label(MessageHelper.getMessage("widget.mode.popup.field.foreground"))
textField().bindText(modeColors::insertFg)
}.layout(RowLayout.PARENT_GRID)
}

group(MessageHelper.getMessage("widget.mode.popup.group.replace.title")) {
row {
label(MessageHelper.getMessage("widget.mode.popup.field.background"))
textField().bindText(modeColors::replaceBg)
}.layout(RowLayout.PARENT_GRID)
row {
label(MessageHelper.getMessage("widget.mode.popup.field.foreground"))
textField().bindText(modeColors::replaceFg)
}.layout(RowLayout.PARENT_GRID)
}

group(MessageHelper.getMessage("widget.mode.popup.group.command.title")) {
row {
label(MessageHelper.getMessage("widget.mode.popup.field.background"))
textField().bindText(modeColors::commandBg)
}.layout(RowLayout.PARENT_GRID)
row {
label(MessageHelper.getMessage("widget.mode.popup.field.foreground"))
textField().bindText(modeColors::commandFg)
}.layout(RowLayout.PARENT_GRID)
}
label(MessageHelper.getMessage("widget.mode.popup.field.theme"))
comboBox(ModeWidgetTheme.values().toList()).bindItem(modeColors::theme.toNullableProperty())
}
row { browserLink("Suggest your theme", "https://youtrack.jetbrains.com/issue/VIM-1377/Normal-mode-needs-to-be-more-obvious") }
}.topGap(TopGap.NONE).visibleIf(!advancedSettings.selected)
group(MessageHelper.getMessage("widget.mode.popup.group.title.full.customization")) {
row { text(MessageHelper.getMessage("widget.mode.popup.color.instruction")) }

group(MessageHelper.getMessage("widget.mode.popup.group.visual.title")) {
row {
label(MessageHelper.getMessage("widget.mode.popup.field.background"))
textField().bindText(modeColors::visualBg)
}.layout(RowLayout.PARENT_GRID)
row {
label(MessageHelper.getMessage("widget.mode.popup.field.foreground"))
textField().bindText(modeColors::visualFg)
}.layout(RowLayout.PARENT_GRID)
group(MessageHelper.getMessage("widget.mode.popup.group.normal.title")) {
row {
label(MessageHelper.getMessage("widget.mode.popup.field.background"))
textField().bindText(modeColors::normalBg)
}.layout(RowLayout.PARENT_GRID)
row {
label(MessageHelper.getMessage("widget.mode.popup.field.foreground"))
textField().bindText(modeColors::normalFg)
}.layout(RowLayout.PARENT_GRID)
}

collapsibleGroup(MessageHelper.getMessage("widget.mode.popup.group.visual.subgroup.line.title")) {
row { text(MessageHelper.getMessage("widget.mode.popup.group.visual.subgroup.instruction")) }
group(MessageHelper.getMessage("widget.mode.popup.group.insert.title")) {
row {
label(MessageHelper.getMessage("widget.mode.popup.field.background"))
textField().bindText(modeColors::visualLineBg)
textField().bindText(modeColors::insertBg)
}.layout(RowLayout.PARENT_GRID)
row {
label(MessageHelper.getMessage("widget.mode.popup.field.foreground"))
textField().bindText(modeColors::visualLineFg)
textField().bindText(modeColors::insertFg)
}.layout(RowLayout.PARENT_GRID)
}

collapsibleGroup(MessageHelper.getMessage("widget.mode.popup.group.visual.subgroup.block.title")) {
row { text(MessageHelper.getMessage("widget.mode.popup.group.visual.subgroup.instruction")) }
group(MessageHelper.getMessage("widget.mode.popup.group.replace.title")) {
row {
label(MessageHelper.getMessage("widget.mode.popup.field.background"))
textField().bindText(modeColors::visualBlockBg)
textField().bindText(modeColors::replaceBg)
}.layout(RowLayout.PARENT_GRID)
row {
label(MessageHelper.getMessage("widget.mode.popup.field.foreground"))
textField().bindText(modeColors::visualBlockFg)
textField().bindText(modeColors::replaceFg)
}.layout(RowLayout.PARENT_GRID)
}
}

group(MessageHelper.getMessage("widget.mode.popup.group.select.title")) {
row {
label(MessageHelper.getMessage("widget.mode.popup.field.background"))
textField().bindText(modeColors::selectBg)
}.layout(RowLayout.PARENT_GRID)
row {
label(MessageHelper.getMessage("widget.mode.popup.field.foreground"))
textField().bindText(modeColors::selectFg)
}.layout(RowLayout.PARENT_GRID)
group(MessageHelper.getMessage("widget.mode.popup.group.command.title")) {
row {
label(MessageHelper.getMessage("widget.mode.popup.field.background"))
textField().bindText(modeColors::commandBg)
}.layout(RowLayout.PARENT_GRID)
row {
label(MessageHelper.getMessage("widget.mode.popup.field.foreground"))
textField().bindText(modeColors::commandFg)
}.layout(RowLayout.PARENT_GRID)
}

collapsibleGroup(MessageHelper.getMessage("widget.mode.popup.group.select.subgroup.line.title")) {
row { text(MessageHelper.getMessage("widget.mode.popup.group.select.subgroup.instruction")) }
group(MessageHelper.getMessage("widget.mode.popup.group.visual.title")) {
row {
label(MessageHelper.getMessage("widget.mode.popup.field.background"))
textField().bindText(modeColors::selectLineBg)
textField().bindText(modeColors::visualBg)
}.layout(RowLayout.PARENT_GRID)
row {
label(MessageHelper.getMessage("widget.mode.popup.field.foreground"))
textField().bindText(modeColors::selectLineFg)
textField().bindText(modeColors::visualFg)
}.layout(RowLayout.PARENT_GRID)

collapsibleGroup(MessageHelper.getMessage("widget.mode.popup.group.visual.subgroup.line.title")) {
row { text(MessageHelper.getMessage("widget.mode.popup.group.visual.subgroup.instruction")) }
row {
label(MessageHelper.getMessage("widget.mode.popup.field.background"))
textField().bindText(modeColors::visualLineBg)
}.layout(RowLayout.PARENT_GRID)
row {
label(MessageHelper.getMessage("widget.mode.popup.field.foreground"))
textField().bindText(modeColors::visualLineFg)
}.layout(RowLayout.PARENT_GRID)
}

collapsibleGroup(MessageHelper.getMessage("widget.mode.popup.group.visual.subgroup.block.title")) {
row { text(MessageHelper.getMessage("widget.mode.popup.group.visual.subgroup.instruction")) }
row {
label(MessageHelper.getMessage("widget.mode.popup.field.background"))
textField().bindText(modeColors::visualBlockBg)
}.layout(RowLayout.PARENT_GRID)
row {
label(MessageHelper.getMessage("widget.mode.popup.field.foreground"))
textField().bindText(modeColors::visualBlockFg)
}.layout(RowLayout.PARENT_GRID)
}
}

collapsibleGroup(MessageHelper.getMessage("widget.mode.popup.group.select.subgroup.block.title")) {
row { text(MessageHelper.getMessage("widget.mode.popup.group.select.subgroup.instruction")) }
group(MessageHelper.getMessage("widget.mode.popup.group.select.title")) {
row {
label(MessageHelper.getMessage("widget.mode.popup.field.background"))
textField().bindText(modeColors::selectBlockBg)
textField().bindText(modeColors::selectBg)
}.layout(RowLayout.PARENT_GRID)
row {
label(MessageHelper.getMessage("widget.mode.popup.field.foreground"))
textField().bindText(modeColors::selectBlockFg)
textField().bindText(modeColors::selectFg)
}.layout(RowLayout.PARENT_GRID)

collapsibleGroup(MessageHelper.getMessage("widget.mode.popup.group.select.subgroup.line.title")) {
row { text(MessageHelper.getMessage("widget.mode.popup.group.select.subgroup.instruction")) }
row {
label(MessageHelper.getMessage("widget.mode.popup.field.background"))
textField().bindText(modeColors::selectLineBg)
}.layout(RowLayout.PARENT_GRID)
row {
label(MessageHelper.getMessage("widget.mode.popup.field.foreground"))
textField().bindText(modeColors::selectLineFg)
}.layout(RowLayout.PARENT_GRID)
}

collapsibleGroup(MessageHelper.getMessage("widget.mode.popup.group.select.subgroup.block.title")) {
row { text(MessageHelper.getMessage("widget.mode.popup.group.select.subgroup.instruction")) }
row {
label(MessageHelper.getMessage("widget.mode.popup.field.background"))
textField().bindText(modeColors::selectBlockBg)
}.layout(RowLayout.PARENT_GRID)
row {
label(MessageHelper.getMessage("widget.mode.popup.field.foreground"))
textField().bindText(modeColors::selectBlockFg)
}.layout(RowLayout.PARENT_GRID)
}
}
}
}.topGap(TopGap.NONE).visibleIf(advancedSettings.selected)
}
return panel
}
Expand All @@ -262,35 +286,48 @@ public class ModeWidgetPopup : AnAction() {
}

private class ModeColors(
isFullCustomizationKey: String, themeKey: String,
normalBgKey: String, normalFgKey: String,
insertBgKey: String, insertFgKey: String,
replaceBgKey: String, replaceFgKey: String,
commandBgKey: String, commandFgKey: String,
visualBgKey: String, visualFgKey: String, visualLineBgKey: String, visualLineFgKey: String, visualBlockBgKey: String, visualBlockFgKey: String,
selectBgKey: String, selectFgKey: String, selectLineBgKey: String, selectLineFgKey: String, selectBlockBgKey: String, selectBlockFgKey: String
) {
var normalBg: String by VimScopeVariable(normalBgKey)
var normalFg: String by VimScopeVariable(normalFgKey)
var insertBg: String by VimScopeVariable(insertBgKey)
var insertFg: String by VimScopeVariable(insertFgKey)
var replaceBg: String by VimScopeVariable(replaceBgKey)
var replaceFg: String by VimScopeVariable(replaceFgKey)
var commandBg: String by VimScopeVariable(commandBgKey)
var commandFg: String by VimScopeVariable(commandFgKey)
var visualBg: String by VimScopeVariable(visualBgKey)
var visualFg: String by VimScopeVariable(visualFgKey)
var visualLineBg: String by VimScopeVariable(visualLineBgKey)
var visualLineFg: String by VimScopeVariable(visualLineFgKey)
var visualBlockBg: String by VimScopeVariable(visualBlockBgKey)
var visualBlockFg: String by VimScopeVariable(visualBlockFgKey)
var selectBg: String by VimScopeVariable(selectBgKey)
var selectFg: String by VimScopeVariable(selectFgKey)
var selectLineBg: String by VimScopeVariable(selectLineBgKey)
var selectLineFg: String by VimScopeVariable(selectLineFgKey)
var selectBlockBg: String by VimScopeVariable(selectBlockBgKey)
var selectBlockFg: String by VimScopeVariable(selectBlockFgKey)

private class VimScopeVariable(private var key: String): ReadWriteProperty<ModeColors, String> {
var isFullCustomization: Boolean by VimScopeBooleanVariable(isFullCustomizationKey)
var theme: ModeWidgetTheme by VimScopeThemeVariable(themeKey)
var normalBg: String by VimScopeStringVariable(normalBgKey)
var normalFg: String by VimScopeStringVariable(normalFgKey)
var insertBg: String by VimScopeStringVariable(insertBgKey)
var insertFg: String by VimScopeStringVariable(insertFgKey)
var replaceBg: String by VimScopeStringVariable(replaceBgKey)
var replaceFg: String by VimScopeStringVariable(replaceFgKey)
var commandBg: String by VimScopeStringVariable(commandBgKey)
var commandFg: String by VimScopeStringVariable(commandFgKey)
var visualBg: String by VimScopeStringVariable(visualBgKey)
var visualFg: String by VimScopeStringVariable(visualFgKey)
var visualLineBg: String by VimScopeStringVariable(visualLineBgKey)
var visualLineFg: String by VimScopeStringVariable(visualLineFgKey)
var visualBlockBg: String by VimScopeStringVariable(visualBlockBgKey)
var visualBlockFg: String by VimScopeStringVariable(visualBlockFgKey)
var selectBg: String by VimScopeStringVariable(selectBgKey)
var selectFg: String by VimScopeStringVariable(selectFgKey)
var selectLineBg: String by VimScopeStringVariable(selectLineBgKey)
var selectLineFg: String by VimScopeStringVariable(selectLineFgKey)
var selectBlockBg: String by VimScopeStringVariable(selectBlockBgKey)
var selectBlockFg: String by VimScopeStringVariable(selectBlockFgKey)

private class VimScopeBooleanVariable(private var key: String): ReadWriteProperty<ModeColors, Boolean> {
override fun getValue(thisRef: ModeColors, property: KProperty<*>): Boolean {
return injector.variableService.getVimVariable(key)?.asBoolean() ?: false
}

override fun setValue(thisRef: ModeColors, property: KProperty<*>, value: Boolean) {
injector.variableService.storeVimVariable(key, value.asVimInt())
}
}

private class VimScopeStringVariable(private var key: String): ReadWriteProperty<ModeColors, String> {
override fun getValue(thisRef: ModeColors, property: KProperty<*>): String {
return injector.variableService.getVimVariable(key)?.asString() ?: ""
}
Expand All @@ -299,5 +336,33 @@ public class ModeWidgetPopup : AnAction() {
injector.variableService.storeVimVariable(key, VimString(value))
}
}

private class VimScopeThemeVariable(private var key: String): ReadWriteProperty<ModeColors, ModeWidgetTheme> {
override fun getValue(thisRef: ModeColors, property: KProperty<*>): ModeWidgetTheme {
val themeString = injector.variableService.getVimVariable(key)?.asString() ?: return ModeWidgetTheme.getDefaultTheme()
return ModeWidgetTheme.parseString(themeString) ?: ModeWidgetTheme.getDefaultTheme()
}

override fun setValue(thisRef: ModeColors, property: KProperty<*>, value: ModeWidgetTheme) {
injector.variableService.storeVimVariable(key, VimString(value.toString()))
}
}
}
}

public enum class ModeWidgetTheme(private var value: String) {
TEST("Nord-Aurora (testing, will be removed)"),
COLORLESS("Colorless");

override fun toString(): String {
return value
}

public companion object {
public fun parseString(string: String): ModeWidgetTheme? {
return ModeWidgetTheme.values().firstOrNull { it.value == string }
}

public fun getDefaultTheme(): ModeWidgetTheme = TEST
}
}
Loading

0 comments on commit fb75508

Please sign in to comment.