From ef12431a8746a661cface51fc359a5bc39fe3982 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 15 Apr 2019 19:10:46 +0200 Subject: [PATCH] Finish converting EditorTabsConfigurable to property bindings --- .../src/PasswordSafeConfigurable.kt | 2 +- .../options/editor/EditorTabsConfigurable.kt | 83 ++++--------------- .../src/com/intellij/ui/layout/Cell.kt | 26 +++--- .../intellij/ui/layout/ComponentPredicate.kt | 32 +++++-- .../src/com/intellij/ui/layout/Row.kt | 7 +- 5 files changed, 61 insertions(+), 89 deletions(-) diff --git a/platform/credential-store/src/PasswordSafeConfigurable.kt b/platform/credential-store/src/PasswordSafeConfigurable.kt index 69f082422b1f..c548f76134ba 100644 --- a/platform/credential-store/src/PasswordSafeConfigurable.kt +++ b/platform/credential-store/src/PasswordSafeConfigurable.kt @@ -227,7 +227,7 @@ internal class PasswordSafeConfigurableUi(private val mySettings: PasswordSafeSe { getSelectedPgpKey() ?: pgpListModel.items.firstOrNull() }, { mySettings.state.pgpKeyId = if (usePgpKey.isSelected) it?.keyId else null }, growPolicy = GrowPolicy.MEDIUM_TEXT, - renderer = { value, _, _ -> append("${value.userId} (${value.keyId})") } + renderer = listCellRenderer { value, _, _ -> append("${value.userId} (${value.keyId})") } ) .enableIf(usePgpKey.selected) .component diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.kt b/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.kt index 93853daf08f3..7ade72514801 100644 --- a/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.kt +++ b/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.kt @@ -20,42 +20,14 @@ class EditorTabsConfigurable : EditorOptionsProvider { private const val NONE = "None" private val EDITOR_TABS_RANGE = UINumericRange(10, 1, Math.max(10, Registry.intValue("ide.max.editor.tabs", 100))) + val tabPlacements = arrayOf(SwingConstants.TOP, SwingConstants.LEFT, SwingConstants.BOTTOM, SwingConstants.RIGHT, UISettings.TABS_NONE) } - private val myEditorTabPlacement: JComboBox = ComboBox( - arrayOf(SwingConstants.TOP, SwingConstants.LEFT, SwingConstants.BOTTOM, SwingConstants.RIGHT, UISettings.TABS_NONE) - ) - private val myScrollTabLayoutInEditorCheckBox = JCheckBox(message("checkbox.editor.tabs.in.single.row")) - private val myHideTabsCheckbox = JCheckBox(message("checkbox.editor.scroll.if.need")) - private lateinit var myCloseButtonPlacementRow: Row + private lateinit var myEditorTabPlacement: JComboBox + private lateinit var myScrollTabLayoutInEditorCheckBox: JCheckBox private val panel = doCreateComponent() - init { - myEditorTabPlacement.renderer = MyTabsPlacementComboBoxRenderer() - myEditorTabPlacement.addItemListener { revalidateSingleRowCheckbox() } - - revalidateSingleRowCheckbox() - myScrollTabLayoutInEditorCheckBox.addChangeListener { myHideTabsCheckbox.isEnabled = myScrollTabLayoutInEditorCheckBox.isSelected } - } - - private fun revalidateSingleRowCheckbox() { - val i = (myEditorTabPlacement.selectedItem as Int).toInt() - - val none = i == UISettings.TABS_NONE - myHideTabsCheckbox.isEnabled = !none && myScrollTabLayoutInEditorCheckBox.isSelected - myScrollTabLayoutInEditorCheckBox.isEnabled = !none - myCloseButtonPlacementRow.enabled = !none - - if (SwingConstants.TOP == i) { - myScrollTabLayoutInEditorCheckBox.isEnabled = true - } - else { - myScrollTabLayoutInEditorCheckBox.isSelected = true - myScrollTabLayoutInEditorCheckBox.isEnabled = false - } - } - - override fun getDisplayName() = "Editor Tabs (New)" + override fun getDisplayName() = "Editor Tabs" override fun getHelpTopic() = "reference.settingsdialog.IDE.editor.tabs" @@ -71,13 +43,17 @@ class EditorTabsConfigurable : EditorOptionsProvider { row { cell { Label(message("combobox.editor.tab.placement"))() - myEditorTabPlacement() + myEditorTabPlacement = comboBox(DefaultComboBoxModel(tabPlacements), uiSettings::editorTabPlacement, + renderer = MyTabsPlacementComboBoxRenderer()).component } } row { - myScrollTabLayoutInEditorCheckBox() + myScrollTabLayoutInEditorCheckBox = checkBox(message("checkbox.editor.tabs.in.single.row"), uiSettings::scrollTabLayoutInEditor) + .enableIf(myEditorTabPlacement.selectedValueIs(SwingConstants.TOP)).component row { - myHideTabsCheckbox() + checkBox(message("checkbox.editor.scroll.if.need"), uiSettings::hideTabsIfNeed) + .enableIf(myEditorTabPlacement.selectedValueMatches { it != UISettings.TABS_NONE } and + myScrollTabLayoutInEditorCheckBox.selected) } } row { @@ -90,7 +66,7 @@ class EditorTabsConfigurable : EditorOptionsProvider { row { checkBox(message("checkbox.show.directory.for.non.unique.files"), uiSettings::showDirectoryForNonUniqueFilenames).enableIfTabsVisible() } row { checkBox(message("checkbox.mark.modified.tabs.with.asterisk"), uiSettings::markModifiedTabsWithAsterisk).enableIfTabsVisible() } row { checkBox(message("checkbox.show.tabs.tooltips"), uiSettings::showTabsTooltips).enableIfTabsVisible() } - myCloseButtonPlacementRow = row { + row { cell { Label(message("tabs.close.button.placement"))() comboBox( @@ -104,7 +80,7 @@ class EditorTabsConfigurable : EditorOptionsProvider { } ) } - } + }.enableIf((myEditorTabPlacement.selectedValueMatches { it != UISettings.TABS_NONE })) } titledRow(message("group.tab.closing.policy")) { row { @@ -140,18 +116,11 @@ class EditorTabsConfigurable : EditorOptionsProvider { } private fun CellBuilder.enableIfTabsVisible() { - enableIf(myEditorTabPlacement.hasSelection { it != UISettings.TABS_NONE }) + enableIf(myEditorTabPlacement.selectedValueMatches { it != UISettings.TABS_NONE }) } override fun reset() { panel.reset() - - val uiSettings = UISettings.instance.state - - myScrollTabLayoutInEditorCheckBox.isSelected = uiSettings.scrollTabLayoutInEditor - myHideTabsCheckbox.isEnabled = myScrollTabLayoutInEditorCheckBox.isSelected - myHideTabsCheckbox.isSelected = uiSettings.hideTabsIfNeed - myEditorTabPlacement.selectedItem = uiSettings.editorTabPlacement } private fun getCloseButtonPlacement(uiSettings: UISettingsState): String { @@ -166,20 +135,9 @@ class EditorTabsConfigurable : EditorOptionsProvider { } override fun apply() { - var uiSettingsChanged = panel.isModified() + val uiSettingsChanged = panel.isModified() panel.apply() val settingsManager = UISettings.instance - val uiSettings = settingsManager.state - - if (isModified(myScrollTabLayoutInEditorCheckBox, uiSettings.scrollTabLayoutInEditor)) uiSettingsChanged = true - uiSettings.scrollTabLayoutInEditor = myScrollTabLayoutInEditorCheckBox.isSelected - - if (isModified(myHideTabsCheckbox, uiSettings.hideTabsIfNeed)) uiSettingsChanged = true - uiSettings.hideTabsIfNeed = myHideTabsCheckbox.isSelected - - val tabPlacement = (myEditorTabPlacement.selectedItem as Int).toInt() - if (uiSettings.editorTabPlacement != tabPlacement) uiSettingsChanged = true - uiSettings.editorTabPlacement = tabPlacement if (uiSettingsChanged) { settingsManager.fireUISettingsChanged() @@ -187,16 +145,7 @@ class EditorTabsConfigurable : EditorOptionsProvider { } override fun isModified(): Boolean { - if (panel.isModified()) return true - - val uiSettings = UISettings.instance.state - val tabPlacement = (myEditorTabPlacement.selectedItem as Int).toInt() - var isModified = tabPlacement != uiSettings.editorTabPlacement - - isModified = isModified or (myScrollTabLayoutInEditorCheckBox.isSelected != uiSettings.scrollTabLayoutInEditor) - isModified = isModified or (myHideTabsCheckbox.isSelected != uiSettings.hideTabsIfNeed) - - return isModified + return panel.isModified() } private class MyTabsPlacementComboBoxRenderer internal constructor() : ListCellRendererWrapper() { diff --git a/platform/platform-impl/src/com/intellij/ui/layout/Cell.kt b/platform/platform-impl/src/com/intellij/ui/layout/Cell.kt index 33afbb11c84b..734de2b11c35 100644 --- a/platform/platform-impl/src/com/intellij/ui/layout/Cell.kt +++ b/platform/platform-impl/src/com/intellij/ui/layout/Cell.kt @@ -172,20 +172,8 @@ abstract class Cell { return builder.withBinding({ component.selectedItem as T? }, { component.setSelectedItem(it) }, getter, setter) } - fun comboBox( - model: ComboBoxModel, - getter: () -> T?, - setter: (T?) -> Unit, - growPolicy: GrowPolicy? = null, - renderer: ColoredListCellRenderer.(value: T, index: Int, isSelected: Boolean) -> Unit - ): CellBuilder> { - return comboBox(model, getter, setter, growPolicy, object : ColoredListCellRenderer() { - override fun customizeCellRenderer(list: JList, value: T?, index: Int, selected: Boolean, hasFocus: Boolean) { - if (value != null) { - renderer(this, value, index, selected) - } - } - }) + fun comboBox(model: ComboBoxModel, prop: KMutableProperty0, growPolicy: GrowPolicy? = null, renderer: ListCellRenderer? = null): CellBuilder> { + return comboBox(model, prop.getter, { prop.set(it!!) }, growPolicy, renderer) } fun textField(prop: KMutableProperty0, columns: Int? = null): CellBuilder { @@ -280,3 +268,13 @@ abstract class Cell { ): CellBuilder } + +fun listCellRenderer(renderer: ColoredListCellRenderer.(value: T, index: Int, isSelected: Boolean) -> Unit): ColoredListCellRenderer { + return object : ColoredListCellRenderer() { + override fun customizeCellRenderer(list: JList, value: T?, index: Int, selected: Boolean, hasFocus: Boolean) { + if (value != null) { + renderer(this, value, index, selected) + } + } + } +} diff --git a/platform/platform-impl/src/com/intellij/ui/layout/ComponentPredicate.kt b/platform/platform-impl/src/com/intellij/ui/layout/ComponentPredicate.kt index 31d78d7734f4..eb125d0d8e00 100644 --- a/platform/platform-impl/src/com/intellij/ui/layout/ComponentPredicate.kt +++ b/platform/platform-impl/src/com/intellij/ui/layout/ComponentPredicate.kt @@ -13,16 +13,36 @@ val AbstractButton.selected: ComponentPredicate override fun invoke(): Boolean = isSelected override fun addListener(listener: (Boolean) -> Unit) { - addChangeListener { listener(isSelected()) } + addChangeListener { listener(isSelected) } } } -fun JComboBox.hasSelection(predicate: (T?) -> Boolean): ComponentPredicate { - return object : ComponentPredicate() { - override fun invoke(): Boolean = predicate(selectedItem as T?) +fun JComboBox.selectedValueMatches(predicate: (T?) -> Boolean): ComponentPredicate { + return ComboBoxPredicate(this, predicate) +} - override fun addListener(listener: (Boolean) -> Unit) { - addActionListener { listener(predicate(selectedItem as T?)) } +class ComboBoxPredicate(private val comboBox: JComboBox, private val predicate: (T?) -> Boolean) : ComponentPredicate() { + override fun invoke(): Boolean = predicate(comboBox.selectedItem as T?) + + override fun addListener(listener: (Boolean) -> Unit) { + comboBox.addActionListener { + listener(predicate(comboBox.selectedItem as T?)) } } } + +fun JComboBox.selectedValueIs(value: T): ComponentPredicate = selectedValueMatches { it == value } + +infix fun ComponentPredicate.and(other: ComponentPredicate): ComponentPredicate { + return AndPredicate(this, other) +} + +private class AndPredicate(private val lhs: ComponentPredicate, private val rhs: ComponentPredicate) : ComponentPredicate() { + override fun invoke(): Boolean = lhs.invoke() && rhs.invoke() + + override fun addListener(listener: (Boolean) -> Unit) { + val andListener: (Boolean) -> Unit = { listener(lhs.invoke() && rhs.invoke()) } + lhs.addListener(andListener) + rhs.addListener(andListener) + } +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ui/layout/Row.kt b/platform/platform-impl/src/com/intellij/ui/layout/Row.kt index 5bf0d1fdb0c9..0c8a1451cd41 100644 --- a/platform/platform-impl/src/com/intellij/ui/layout/Row.kt +++ b/platform/platform-impl/src/com/intellij/ui/layout/Row.kt @@ -92,4 +92,9 @@ abstract class Row : Cell() { enum class GrowPolicy { SHORT_TEXT, MEDIUM_TEXT -} \ No newline at end of file +} + +fun Row.enableIf(predicate: ComponentPredicate) { + enabled = predicate() + predicate.addListener { enabled = it } +}