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
4 import com.intellij.execution.runToolbar.data.RWSlotManagerState
5 import com.intellij.execution.runToolbar.data.RWStateListener
6 import com.intellij.ide.DataManager
7 import com.intellij.openapi.actionSystem.*
8 import com.intellij.openapi.diagnostic.Logger
9 import com.intellij.openapi.project.Project
10 import com.intellij.openapi.util.Disposer
11 import com.intellij.openapi.wm.IdeFrame
12 import java.awt.event.ContainerEvent
13 import java.awt.event.ContainerListener
14 import javax.swing.SwingUtilities
16 class RunToolbarMainWidgetComponent(val presentation: Presentation, place: String, group: ActionGroup) :
17 FixWidthSegmentedActionToolbarComponent(place, group) {
19 private val LOG = Logger.getInstance(RunToolbarMainWidgetComponent::class.java)
20 private var counter: MutableMap<Project, Int> = mutableMapOf()
23 override fun logNeeded(): Boolean = RunToolbarProcess.logNeeded
25 private var project: Project? = null
27 if(field == value) return
39 private var popupController: RunToolbarPopupController? = null
41 private val componentListener = object : ContainerListener {
42 override fun componentAdded(e: ContainerEvent) {
43 rebuildPopupControllerComponent()
46 override fun componentRemoved(e: ContainerEvent) {
47 rebuildPopupControllerComponent()
51 private val managerStateListener = object : RWStateListener {
52 override fun stateChanged(state: RWSlotManagerState) {
57 private var state: RunToolbarMainSlotState? = null
59 private fun updateState() {
60 state = project?.let {
61 val slotManager = RunToolbarSlotManager.getInstance(it)
62 val value = when (slotManager.getState()) {
63 RWSlotManagerState.SINGLE_MAIN -> {
64 RunToolbarMainSlotState.PROCESS
66 RWSlotManagerState.SINGLE_PLAIN,
67 RWSlotManagerState.MULTIPLE -> {
68 if(isOpened) RunToolbarMainSlotState.CONFIGURATION else RunToolbarMainSlotState.INFO
70 RWSlotManagerState.INACTIVE -> {
71 RunToolbarMainSlotState.CONFIGURATION
73 RWSlotManagerState.MULTIPLE_WITH_MAIN -> {
74 if(isOpened) RunToolbarMainSlotState.PROCESS else RunToolbarMainSlotState.INFO
81 if(RunToolbarProcess.logNeeded) LOG.info("MAIN SLOT state updated: $state RunToolbar")
84 override fun traceState(lastIds: List<String>, filteredIds: List<String>, ides: List<String>) {
85 if(logNeeded() && filteredIds != lastIds) LOG.info("MAIN SLOT state: ${state} new filtered: ${filteredIds}} visible: $ides RunToolbar")
88 internal var isOpened = false
90 if(field == value) return
93 if(RunToolbarProcess.logNeeded) LOG.info("MAIN SLOT isOpened: $isOpened RunToolbar")
96 if (RunToolbarProcess.isExperimentalUpdatingEnabled) {
101 override fun isSuitableAction(action: AnAction): Boolean {
103 if(action is RTBarAction) {
104 action.checkMainSlotVisibility(it)
109 override fun addNotify() {
112 (SwingUtilities.getWindowAncestor(this) as? IdeFrame)?.project?.let {
115 RUN_CONFIG_WIDTH = RunToolbarSettings.getInstance(it).getRunConfigWidth()
120 override fun updateWidthHandler() {
121 super.updateWidthHandler()
123 RunToolbarSettings.getInstance(it).setRunConfigWidth(RUN_CONFIG_WIDTH)
127 private fun rebuildPopupControllerComponent() {
128 popupController?.let {
129 it.updateControllerComponents(components.filter{it is PopupControllerComponent}.toMutableList())
133 override fun removeNotify() {
138 private fun add(project: Project) {
139 popupController = RunToolbarPopupController(project, this)
141 val value = counter.getOrDefault(project, 0) + 1
142 counter[project] = value
143 val slotManager = RunToolbarSlotManager.getInstance(project)
144 DataManager.registerDataProvider(component, DataProvider { key ->
146 RunToolbarProcessData.RW_SLOT.`is`(key) -> {
147 slotManager.mainSlotData.id
149 RunToolbarData.RUN_TOOLBAR_DATA_KEY.`is`(key) -> {
150 slotManager.mainSlotData
152 RunToolbarData.RUN_TOOLBAR_POPUP_STATE_KEY.`is`(key) -> {
155 RunToolbarData.RUN_TOOLBAR_MAIN_STATE.`is`(key) -> {
163 slotManager.stateListeners.addListener(managerStateListener)
164 slotManager.active = true
167 rebuildPopupControllerComponent()
168 addContainerListener(componentListener)
171 private fun remove(project: Project) {
172 RunToolbarSlotManager.getInstance(project).stateListeners.removeListener(managerStateListener)
173 counter[project]?.let {
174 val value = maxOf(it - 1, 0)
175 counter[project] = value
177 RunToolbarSlotManager.getInstance(project).active = false
178 counter.remove(project)
182 removeContainerListener(componentListener)
183 popupController?.let {
184 if(!Disposer.isDisposed(it)) {
188 popupController = null