bacd189f0859d250f17be94c4d4b04f3fb6bc5cc
[idea/community.git] / platform / vcs-impl / src / com / intellij / openapi / vcs / configurable / VcsGeneralSettingsConfigurable.kt
1 // Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 package com.intellij.openapi.vcs.configurable
3
4 import com.intellij.application.options.editor.checkBox
5 import com.intellij.ide.actions.RevealFileAction
6 import com.intellij.openapi.application.ApplicationNamesInfo
7 import com.intellij.openapi.application.runInEdt
8 import com.intellij.openapi.options.BoundSearchableConfigurable
9 import com.intellij.openapi.options.Configurable
10 import com.intellij.openapi.options.Configurable.NoScroll
11 import com.intellij.openapi.project.Project
12 import com.intellij.openapi.ui.ComboBox
13 import com.intellij.openapi.ui.DialogPanel
14 import com.intellij.openapi.vcs.ProjectLevelVcsManager
15 import com.intellij.openapi.vcs.VcsBundle.message
16 import com.intellij.openapi.vcs.VcsConfiguration
17 import com.intellij.openapi.vcs.VcsListener
18 import com.intellij.openapi.vcs.VcsShowConfirmationOption
19 import com.intellij.openapi.vcs.changes.RemoteRevisionsCache
20 import com.intellij.openapi.vcs.contentAnnotation.VcsContentAnnotationSettings
21 import com.intellij.openapi.vcs.ex.ProjectLevelVcsManagerEx
22 import com.intellij.openapi.vcs.impl.VcsEP
23 import com.intellij.openapi.vcs.impl.projectlevelman.PersistentVcsSetting
24 import com.intellij.ui.EnumComboBoxModel
25 import com.intellij.ui.layout.*
26 import com.intellij.vcsUtil.VcsUtil
27 import org.jetbrains.annotations.Nls
28 import javax.swing.JComponent
29
30 class VcsGeneralSettingsConfigurable(val project: Project)
31   : BoundSearchableConfigurable(message("configurable.VcsGeneralConfigurationConfigurable.display.name"),
32                                 "project.propVCSSupport.Confirmation"), NoScroll, Configurable.WithEpDependencies {
33   override fun getDependencies() = listOf(VcsEP.EP_NAME)
34
35   override fun createPanel(): DialogPanel {
36     val vcsManager = ProjectLevelVcsManagerEx.getInstanceEx(project)
37     val vcsConfiguration = VcsConfiguration.getInstance(project)
38     val contentAnnotationSettings = VcsContentAnnotationSettings.getInstance(project)
39
40     val vcsListeners = mutableListOf<Runnable>()
41     fun updateActiveVcses() {
42       runInEdt {
43         vcsListeners.forEach { it.run() }
44       }
45     }
46     project.messageBus.connect(disposable!!).subscribe(ProjectLevelVcsManager.VCS_CONFIGURATION_CHANGED,
47                                                        VcsListener { updateActiveVcses() })
48     VcsEP.EP_NAME.addChangeListener({ updateActiveVcses() }, disposable)
49
50     return panel {
51       titledRow(message("settings.general.confirmation.group.title")) {
52         fullRow {
53           val addConfirmation = vcsManager.getConfirmation(VcsConfiguration.StandardConfirmation.ADD)
54
55           label(message("settings.border.when.files.are.created"))
56             .withApplicableVcsesTooltip(addConfirmation, vcsListeners)
57           val addComboBox = comboBox(
58             EnumComboBoxModel(VcsShowConfirmationOption.Value::class.java),
59             { addConfirmation.value }, { addConfirmation.value = it },
60             renderer = listCellRenderer { value, _, _ ->
61               setText(when (value) {
62                         VcsShowConfirmationOption.Value.SHOW_CONFIRMATION -> message("radio.after.creation.show.options")
63                         VcsShowConfirmationOption.Value.DO_ACTION_SILENTLY -> message("radio.after.creation.add.silently")
64                         VcsShowConfirmationOption.Value.DO_NOTHING_SILENTLY -> message("radio.after.creation.do.not.add")
65                         else -> ""
66                       })
67             })
68             .withApplicableVcsesTooltip(addConfirmation, vcsListeners)
69
70           checkBox(message("checkbox.including.files.created.outside.ide", ApplicationNamesInfo.getInstance().fullProductName),
71                    vcsConfiguration::ADD_EXTERNAL_FILES_SILENTLY)
72             .enableIf(OptionEnabledPredicate(addComboBox.component))
73             .withLargeLeftGap()
74         }
75         fullRow {
76           val removeConfirmation = vcsManager.getConfirmation(VcsConfiguration.StandardConfirmation.REMOVE)
77
78           label(message("settings.when.files.are.deleted"))
79             .withApplicableVcsesTooltip(removeConfirmation, vcsListeners)
80           comboBox(EnumComboBoxModel(VcsShowConfirmationOption.Value::class.java),
81                    { removeConfirmation.value }, { removeConfirmation.value = it },
82                    renderer = listCellRenderer { value, _, _ ->
83                      setText(when (value) {
84                                VcsShowConfirmationOption.Value.SHOW_CONFIRMATION -> message("radio.after.deletion.show.options")
85                                VcsShowConfirmationOption.Value.DO_ACTION_SILENTLY -> message("radio.after.deletion.remove.silently")
86                                VcsShowConfirmationOption.Value.DO_NOTHING_SILENTLY -> message("radio.after.deletion.do.not.remove")
87                                else -> ""
88                              })
89                    })
90             .withApplicableVcsesTooltip(removeConfirmation, vcsListeners)
91         }
92         fullRow {
93           label(message("settings.general.show.options.before.command.label"))
94
95           for (setting in vcsManager.allOptions) {
96             checkBox(setting.displayName, { setting.value }, { setting.value = it })
97               .withLargeLeftGap()
98               .withApplicableVcsesTooltip(setting, vcsListeners)
99               .visibleIf(OptionVisibleForVcsesPredicate(project, setting, vcsListeners))
100           }
101         }
102         if (project.isDefault || ProjectLevelVcsManager.getInstance(project).allSupportedVcss.any { it.editFileProvider != null }) {
103           fullRow {
104             checkBox(cdShowReadOnlyStatusDialog(project))
105           }
106         }
107       }
108
109       titledRow(message("settings.general.changes.group.title")) {
110         fullRow {
111           val checkBox = checkBox(message("vcs.config.track.changed.on.server"),
112                                   vcsConfiguration::CHECK_LOCALLY_CHANGED_CONFLICTS_IN_BACKGROUND)
113             .onApply {
114               if (!project.isDefault) {
115                 RemoteRevisionsCache.getInstance(project).updateAutomaticRefreshAlarmState(true)
116               }
117             }
118           spinner(vcsConfiguration::CHANGED_ON_SERVER_INTERVAL,
119                   5, 48 * 10 * 60, 5)
120             .enableIf(checkBox.selected)
121           @Suppress("DialogTitleCapitalization")
122           label(message("settings.check.every.minutes"))
123         }
124         fullRow {
125           val checkBox = checkBox(message("settings.checkbox.show.changed.in.last"),
126                                   { contentAnnotationSettings.isShow }, { contentAnnotationSettings.isShow = it })
127             .comment(message("settings.checkbox.show.changed.in.last.comment"))
128           spinner({ contentAnnotationSettings.limitDays }, { contentAnnotationSettings.limitDays = it },
129                   1, VcsContentAnnotationSettings.ourMaxDays, 1)
130             .enableIf(checkBox.selected)
131           @Suppress("DialogTitleCapitalization")
132           label(message("settings.checkbox.measure.days"))
133         }
134         fullRow {
135           checkBox(cdShowDirtyRecursively(project))
136         }
137       }
138
139       blockRow {
140         fullRow {
141           label(message("show.patch.in.explorer.after.creation.label"))
142           comboBox(EnumComboBoxModel(ShowPatchAfterCreationEnum::class.java),
143                    { ShowPatchAfterCreationEnum.getByState(vcsConfiguration.SHOW_PATCH_IN_EXPLORER) },
144                    { vcsConfiguration.SHOW_PATCH_IN_EXPLORER = it?.state })
145         }
146         fullRow {
147           checkBox(message("radio.restore.workspace.on.branch.switching"), vcsConfiguration::RELOAD_CONTEXT)
148             .comment(message("radio.restore.workspace.on.branch.switching.comment"))
149         }
150         fullRow {
151           val checkBox = checkBox(message("settings.checkbox.limit.history.to"), vcsConfiguration::LIMIT_HISTORY)
152           spinner(vcsConfiguration::MAXIMUM_HISTORY_ROWS, 10, 1000000, 10)
153             .enableIf(checkBox.selected)
154           @Suppress("DialogTitleCapitalization")
155           label(message("settings.checkbox.rows"))
156         }
157       }
158     }
159   }
160
161   private fun <T : JComponent> CellBuilder<T>.withApplicableVcsesTooltip(setting: PersistentVcsSetting,
162                                                                          vcsListeners: MutableList<Runnable>): CellBuilder<T> {
163     vcsListeners.add(Runnable { updateApplicableVcsesTooltip(project, component, setting) })
164     updateApplicableVcsesTooltip(project, component, setting)
165     return this
166   }
167 }
168
169 private fun updateApplicableVcsesTooltip(project: Project, component: JComponent, setting: PersistentVcsSetting) {
170   val vcses = setting.getApplicableVcses(project)
171     .map { it.displayName }
172   component.toolTipText = when {
173     vcses.isNotEmpty() -> message("description.text.option.applicable.to.vcses", VcsUtil.joinWithAnd(vcses.toList(), 0))
174     else -> null
175   }
176 }
177
178 private enum class ShowPatchAfterCreationEnum(private val text: () -> @Nls String,
179                                               val state: Boolean?) {
180   ASK({ message("show.patch.in.explorer.after.creation.combobox.text.ask") }, null),
181   YES({ message("show.patch.in.explorer.after.creation.combobox.text.show.in.file.manager", RevealFileAction.getFileManagerName()) }, true),
182   NO({ message("show.patch.in.explorer.after.creation.combobox.text.no") }, false);
183
184   override fun toString(): String = text()
185
186   companion object {
187     fun getByState(state: Boolean?): ShowPatchAfterCreationEnum = when (state) {
188       null -> ASK
189       true -> YES
190       false -> NO
191     }
192   }
193 }
194
195 class OptionEnabledPredicate(private val comboBox: ComboBox<VcsShowConfirmationOption.Value>) : ComponentPredicate() {
196   override fun addListener(listener: (Boolean) -> Unit) {
197     comboBox.addItemListener { listener(invoke()) }
198   }
199
200   override fun invoke(): Boolean = comboBox.item == VcsShowConfirmationOption.Value.DO_ACTION_SILENTLY
201 }
202
203 class OptionVisibleForVcsesPredicate(private val project: Project,
204                                      private val setting: PersistentVcsSetting,
205                                      private val vcsListeners: MutableList<Runnable>) : ComponentPredicate() {
206   override fun addListener(listener: (Boolean) -> Unit) {
207     vcsListeners.add(Runnable { listener(invoke()) })
208   }
209
210   override fun invoke(): Boolean {
211     return project.isDefault ||
212            setting.getApplicableVcses(project).isNotEmpty()
213   }
214 }