4bc27a27d89ce0021232dec392c47a8c59d22f84
[idea/community.git] / platform / execution-impl / src / com / intellij / execution / runToolbar / RunToolbarData.kt
1 // Copyright 2000-2021 JetBrains s.r.o. and contributors. 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.execution.runToolbar
3
4 import com.intellij.execution.RunnerAndConfigurationSettings
5 import com.intellij.execution.executors.ExecutorGroup
6 import com.intellij.execution.impl.EditConfigurationsDialog
7 import com.intellij.execution.impl.ProjectRunConfigurationConfigurable
8 import com.intellij.execution.impl.RunConfigurable
9 import com.intellij.execution.impl.SingleConfigurationConfigurable
10 import com.intellij.execution.runToolbar.data.RWWaitingForAProcesses
11 import com.intellij.execution.runners.ExecutionEnvironment
12 import com.intellij.execution.ui.RunContentDescriptor
13 import com.intellij.icons.AllIcons
14 import com.intellij.ide.DataManager
15 import com.intellij.openapi.actionSystem.*
16 import com.intellij.openapi.options.Configurable
17 import com.intellij.openapi.project.Project
18 import com.intellij.openapi.util.Key
19 import com.intellij.openapi.util.text.HtmlBuilder
20 import com.intellij.openapi.util.text.HtmlChunk
21 import com.intellij.openapi.wm.ToolWindowManager
22 import com.intellij.ui.ColorUtil
23 import com.intellij.util.ui.JBUI
24 import org.jetbrains.annotations.ApiStatus
25 import org.jetbrains.annotations.Nls
26 import javax.swing.Icon
27
28 interface RunToolbarData {
29   companion object {
30     @JvmField val RUN_TOOLBAR_DATA_KEY: DataKey<RunToolbarData> = DataKey.create("RUN_TOOLBAR_DATA_KEY")
31     @JvmField val RUN_TOOLBAR_POPUP_STATE_KEY: DataKey<Boolean> = DataKey.create("RUN_TOOLBAR_POPUP_STATE_KEY")
32     @JvmField val RUN_TOOLBAR_MAIN_STATE: DataKey<RunToolbarMainSlotState> = DataKey.create("RUN_TOOLBAR_MAIN_STATE")
33
34     @ApiStatus.Internal
35     @JvmField val RUN_TOOLBAR_SUPPRESS_MAIN_SLOT_USER_DATA_KEY = Key<Boolean>("RUN_TOOLBAR_SUPPRESS_MAIN_SLOT_USER_DATA_KEY")
36
37     internal fun prepareDescription(@Nls text: String, @Nls description: String): @Nls String {
38       return HtmlBuilder().append(text)
39           .br()
40           .append(
41             HtmlChunk
42               .font(-1)
43               .addText(description)
44               .wrapWith(HtmlChunk.font(ColorUtil.toHtmlColor(JBUI.CurrentTheme.Label.disabledForeground())))).toString()
45     }
46   }
47
48   val id: String
49   var configuration: RunnerAndConfigurationSettings?
50   val environment: ExecutionEnvironment?
51   val waitingForAProcesses: RWWaitingForAProcesses
52
53   fun clear()
54 }
55
56 internal fun RunContentDescriptor.environment(): ExecutionEnvironment? {
57   return this.attachedContent?.component?.let {
58     ExecutionDataKeys.EXECUTION_ENVIRONMENT.getData(DataManager.getInstance().getDataContext(it))
59   }
60 }
61
62 internal fun AnActionEvent.runToolbarData(): RunToolbarData? {
63   return this.dataContext.runToolbarData()
64 }
65
66 fun DataContext.runToolbarData(): RunToolbarData? {
67   return this.getData(RunToolbarData.RUN_TOOLBAR_DATA_KEY)
68 }
69
70 fun AnActionEvent.mainState(): RunToolbarMainSlotState? {
71   return this.dataContext.getData(RunToolbarData.RUN_TOOLBAR_MAIN_STATE)
72 }
73
74 internal fun DataContext.configuration(): RunnerAndConfigurationSettings? {
75   return runToolbarData()?.configuration
76 }
77
78 private fun getConfiguration(dataContext: DataContext): RunnerAndConfigurationSettings? {
79   return dataContext.configuration()
80 }
81
82 internal fun AnActionEvent.isActiveProcess(): Boolean {
83   return this.environment() != null
84 }
85
86 fun RunToolbarData.startWaitingForAProcess(project: Project, settings: RunnerAndConfigurationSettings, executorId: String) {
87   RunToolbarSlotManager.getInstance(project).startWaitingForAProcess(this, settings, executorId)
88 }
89
90 internal fun AnActionEvent.setConfiguration(value: RunnerAndConfigurationSettings?) {
91   this.runToolbarData()?.configuration = value
92 }
93
94 internal fun DataContext.setConfiguration(value: RunnerAndConfigurationSettings?) {
95   runToolbarData()?.configuration = value
96 }
97
98 internal fun AnActionEvent.configuration(): RunnerAndConfigurationSettings? {
99   return runToolbarData()?.configuration
100 }
101
102 internal fun AnActionEvent.arrowIcon(): Icon? {
103   val isOpened = this.dataContext.getData(RunToolbarData.RUN_TOOLBAR_POPUP_STATE_KEY)
104                  ?: return null
105   return when {
106     isOpened -> {
107       AllIcons.Toolbar.Collapse
108     }
109     else -> {
110       AllIcons.Toolbar.Expand
111     }
112   }
113 }
114
115 fun ExecutionEnvironment.getDisplayName(): String? {
116   return this.contentToReuse?.displayName
117 }
118
119 fun AnActionEvent.environment(): ExecutionEnvironment? {
120   return runToolbarData()?.environment
121 }
122
123 fun ExecutionEnvironment.isRunning(): Boolean? {
124   return this.contentToReuse?.processHandler?.let {
125     !it.isProcessTerminating && !it.isProcessTerminated
126   }
127 }
128
129
130 fun AnActionEvent.isProcessTerminating(): Boolean {
131   return this.environment()?.isProcessTerminating() == true
132 }
133
134 fun ExecutionEnvironment.isProcessTerminating(): Boolean {
135   return this.contentToReuse?.processHandler?.isProcessTerminating == true
136 }
137
138 internal fun AnActionEvent.id(): String? {
139   return runToolbarData()?.id
140 }
141
142 internal fun ExecutionEnvironment.getRunToolbarProcess(): RunToolbarProcess? {
143   return ExecutorGroup.getGroupIfProxy(this.executor)?.let { executorGroup ->
144     RunToolbarProcess.getProcesses().firstOrNull {
145       it.executorId == executorGroup.id
146     }
147   } ?: run {
148     RunToolbarProcess.getProcesses().firstOrNull {
149       it.executorId == this.executor.id
150     }
151   }
152 }
153
154 internal fun DataContext.editConfiguration() {
155   getData(CommonDataKeys.PROJECT)?.let {
156     EditConfigurationsDialog(it, createRunConfigurationConfigurable(it, this)).show()
157   }
158 }
159
160 internal fun ExecutionEnvironment.showToolWindowTab() {
161   ToolWindowManager.getInstance(this.project).getToolWindow(this.contentToReuse?.contentToolWindowId ?: this.executor.id)?.let {
162     val contentManager = it.contentManager
163     contentManager.contents.firstOrNull { it.executionId == this.executionId }?.let { content ->
164       contentManager.setSelectedContent(content)
165     }
166     it.show()
167   }
168 }
169
170 private fun createRunConfigurationConfigurable(project: Project, dataContext: DataContext): RunConfigurable {
171   val settings: RunnerAndConfigurationSettings? = getConfiguration(dataContext)
172
173   fun updateActiveConfigurationFromSelected(configurable: Configurable?) {
174     configurable?.let {
175       if (it is SingleConfigurationConfigurable<*>) {
176         dataContext.setConfiguration(it.settings)
177       }
178     }
179   }
180
181   return when {
182     project.isDefault -> object : RunConfigurable(project) {
183       override fun getSelectedConfiguration(): RunnerAndConfigurationSettings? {
184         return settings
185       }
186
187       override fun updateActiveConfigurationFromSelected() {
188         updateActiveConfigurationFromSelected(getSelectedConfigurable())
189       }
190     }
191     else -> object : ProjectRunConfigurationConfigurable(project) {
192       override fun getSelectedConfiguration(): RunnerAndConfigurationSettings? {
193         return settings
194       }
195
196       override fun updateActiveConfigurationFromSelected() {
197        updateActiveConfigurationFromSelected(getSelectedConfigurable())
198       }
199     }
200   }
201 }