mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IJPL-188924 Rewrite Build for Remote Development
introduce FrontendBuildView GitOrigin-RevId: 6160ceab9240b0c87252da2936ef8dc78b676afd
This commit is contained in:
committed by
intellij-monorepo-bot
parent
ab8f8bd3ef
commit
32a76c8067
@@ -3,6 +3,7 @@ package com.intellij.platform.buildView.frontend
|
||||
|
||||
import com.intellij.build.*
|
||||
import com.intellij.ide.IdeBundle
|
||||
import com.intellij.ide.OccurenceNavigator
|
||||
import com.intellij.ide.OccurenceNavigatorSupport
|
||||
import com.intellij.ide.actions.OccurenceNavigatorActionBase
|
||||
import com.intellij.ide.nls.NlsMessages
|
||||
@@ -56,8 +57,12 @@ import javax.swing.tree.*
|
||||
|
||||
private val LOG = fileLogger()
|
||||
|
||||
internal class BuildTreeView(private val project: Project, parentScope: CoroutineScope, private val buildViewId: BuildViewId)
|
||||
: JPanel(), UiDataProvider, ComponentContainer {
|
||||
internal class BuildTreeView(
|
||||
private val project: Project,
|
||||
parentScope: CoroutineScope,
|
||||
private val buildViewId: BuildViewId,
|
||||
private val backendNavigationAndFiltering: Boolean = true,
|
||||
) : JPanel(), UiDataProvider, ComponentContainer {
|
||||
private val uiScope = parentScope.childScope("BuildTreeView", Dispatchers.UI + ModalityState.any().asContextElement())
|
||||
private val model = BuildTreeViewModelProxy.getInstance(buildViewId)
|
||||
|
||||
@@ -80,6 +85,18 @@ internal class BuildTreeView(private val project: Project, parentScope: Coroutin
|
||||
|
||||
private val occurenceNavigatorSupport = MyOccurenceNavigatorSupport(tree)
|
||||
|
||||
internal var showingSuccessful: Boolean
|
||||
get() = filteringState.showSuccessful
|
||||
set(value) {
|
||||
handleFilteringStateChange(filteringState.copy(showSuccessful = value))
|
||||
}
|
||||
|
||||
internal var showingWarnings: Boolean
|
||||
get() = filteringState.showWarnings
|
||||
set(value) {
|
||||
handleFilteringStateChange(filteringState.copy(showWarnings = value))
|
||||
}
|
||||
|
||||
// A factor which can correct for the difference between frontend's and backend's clocks,
|
||||
// in case we need to display a duration of a process, for which we know the start timestamp on the backend.
|
||||
// It doesn't include the connection latency, but that seems acceptable in our case.
|
||||
@@ -98,15 +115,17 @@ internal class BuildTreeView(private val project: Project, parentScope: Coroutin
|
||||
handleTreeEvent(event, nodeMap)
|
||||
}
|
||||
}
|
||||
uiScope.launch(Dispatchers.EDT /* Navigatable-s might expect WIL to be taken */) {
|
||||
model.getNavigationFlow().collect {
|
||||
handleNavigation(it.forward)
|
||||
if (backendNavigationAndFiltering) {
|
||||
uiScope.launch(Dispatchers.EDT /* Navigatable-s might expect WIL to be taken */) {
|
||||
model.getNavigationFlow().collect {
|
||||
handleNavigation(it.forward)
|
||||
}
|
||||
}
|
||||
}
|
||||
uiScope.launch {
|
||||
navigationContext.collect {
|
||||
LOG.debug { "Navigation context: $it" }
|
||||
model.onNavigationContextChange(it)
|
||||
uiScope.launch {
|
||||
navigationContext.collect {
|
||||
LOG.debug { "Navigation context: $it" }
|
||||
model.onNavigationContextChange(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -219,7 +238,7 @@ internal class BuildTreeView(private val project: Project, parentScope: Coroutin
|
||||
val nodeId = event.nodeId
|
||||
if (nodeId == null) {
|
||||
LOG.debug { "Clearing selection" }
|
||||
tree.clearSelection()
|
||||
clearTreeSelection()
|
||||
}
|
||||
else {
|
||||
val node = nodeMap[nodeId]
|
||||
@@ -239,7 +258,9 @@ internal class BuildTreeView(private val project: Project, parentScope: Coroutin
|
||||
}
|
||||
}
|
||||
is BuildTreeFilteringState -> {
|
||||
handleFilteringStateChange(event)
|
||||
if (backendNavigationAndFiltering) {
|
||||
handleFilteringStateChange(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -292,10 +313,12 @@ internal class BuildTreeView(private val project: Project, parentScope: Coroutin
|
||||
}
|
||||
|
||||
private fun updateNavigationContext() {
|
||||
val hasPrevNode = occurenceNavigatorSupport.hasPreviousOccurence()
|
||||
val hasNextNode = occurenceNavigatorSupport.hasNextOccurence()
|
||||
val hasAnyNode = hasNextNode || hasPrevNode || (tree.selectionPath?.lastPathComponent as? MyNode)?.occurrenceNavigatable != null
|
||||
navigationContext.value = BuildTreeNavigationContext(hasPrevNode, hasNextNode, hasAnyNode)
|
||||
if (backendNavigationAndFiltering) {
|
||||
val hasPrevNode = occurenceNavigatorSupport.hasPreviousOccurence()
|
||||
val hasNextNode = occurenceNavigatorSupport.hasNextOccurence()
|
||||
val hasAnyNode = hasNextNode || hasPrevNode || (tree.selectionPath?.lastPathComponent as? MyNode)?.occurrenceNavigatable != null
|
||||
navigationContext.value = BuildTreeNavigationContext(hasPrevNode, hasNextNode, hasAnyNode)
|
||||
}
|
||||
}
|
||||
|
||||
fun maybeExpand(path: TreePath?): Boolean {
|
||||
@@ -337,6 +360,26 @@ internal class BuildTreeView(private val project: Project, parentScope: Coroutin
|
||||
return if (navigatables.isEmpty()) null else navigatables.toTypedArray()
|
||||
}
|
||||
|
||||
internal fun clearTreeSelection() {
|
||||
tree.clearSelection()
|
||||
}
|
||||
|
||||
internal fun hasNextOccurence(): Boolean {
|
||||
return occurenceNavigatorSupport.hasNextOccurence()
|
||||
}
|
||||
|
||||
internal fun hasPreviousOccurence(): Boolean {
|
||||
return occurenceNavigatorSupport.hasPreviousOccurence()
|
||||
}
|
||||
|
||||
internal fun goNextOccurence(): OccurenceNavigator.OccurenceInfo? {
|
||||
return occurenceNavigatorSupport.goNextOccurence()
|
||||
}
|
||||
|
||||
internal fun goPreviousOccurence(): OccurenceNavigator.OccurenceInfo? {
|
||||
return occurenceNavigatorSupport.goPreviousOccurence()
|
||||
}
|
||||
|
||||
private class MyOccurenceNavigatorSupport(tree: JTree) : OccurenceNavigatorSupport(tree) {
|
||||
override fun createDescriptorForNode(node: DefaultMutableTreeNode): Navigatable? {
|
||||
return (node as? MyNode)?.occurrenceNavigatable?.navigatable()
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.platform.buildView.frontend
|
||||
|
||||
import com.intellij.build.BuildTreeConsoleView
|
||||
import com.intellij.build.BuildViewId
|
||||
import com.intellij.build.SuccessfulStepsToggleAction
|
||||
import com.intellij.build.WarningsToggleAction
|
||||
import com.intellij.icons.AllIcons
|
||||
import com.intellij.ide.OccurenceNavigator
|
||||
import com.intellij.ide.rpc.ComponentDirectTransferId
|
||||
import com.intellij.ide.rpc.getComponent
|
||||
import com.intellij.ide.util.PropertiesComponent
|
||||
import com.intellij.lang.LangBundle
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.actionSystem.*
|
||||
import com.intellij.openapi.project.DumbAware
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.NlsContexts
|
||||
import com.intellij.platform.util.coroutines.childScope
|
||||
import com.intellij.ui.OnePixelSplitter
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.cancel
|
||||
import java.awt.BorderLayout
|
||||
import java.lang.ref.Reference
|
||||
import java.lang.ref.WeakReference
|
||||
import javax.swing.JPanel
|
||||
import kotlin.reflect.KMutableProperty1
|
||||
|
||||
internal class FrontendBuildView(
|
||||
project: Project,
|
||||
parentScope: CoroutineScope,
|
||||
treeViewId: BuildViewId?,
|
||||
consoleComponent: ComponentDirectTransferId,
|
||||
) : JPanel(BorderLayout()), Disposable {
|
||||
private val scope = parentScope.childScope("FrontendBuildView")
|
||||
internal val treeView: BuildTreeView?
|
||||
|
||||
init {
|
||||
val console = consoleComponent.getComponent()
|
||||
if (treeViewId != null) {
|
||||
treeView = BuildTreeView(project, scope, treeViewId, false)
|
||||
restoreSavedFiltering(treeView)
|
||||
val splitter = OnePixelSplitter(BuildTreeConsoleView.SPLITTER_PROPERTY, BuildTreeConsoleView.SPLITTER_DEFAULT_PROPORTION).apply {
|
||||
firstComponent = treeView
|
||||
secondComponent = console
|
||||
}
|
||||
add(splitter)
|
||||
}
|
||||
else {
|
||||
treeView = null
|
||||
add(console)
|
||||
}
|
||||
}
|
||||
|
||||
override fun dispose() {
|
||||
scope.cancel()
|
||||
}
|
||||
|
||||
fun hasNextOccurence(): Boolean {
|
||||
return treeView?.hasNextOccurence() ?: false
|
||||
}
|
||||
|
||||
fun hasPreviousOccurence(): Boolean {
|
||||
return treeView?.hasPreviousOccurence() ?: false
|
||||
}
|
||||
|
||||
fun goNextOccurence(): OccurenceNavigator.OccurenceInfo? {
|
||||
return treeView?.goNextOccurence()
|
||||
}
|
||||
|
||||
fun goPreviousOccurence(): OccurenceNavigator.OccurenceInfo? {
|
||||
return treeView?.goPreviousOccurence()
|
||||
}
|
||||
|
||||
fun createFilteringActionGroup(): ActionGroup {
|
||||
val actionGroup = DefaultActionGroup(LangBundle.message("action.filters.text"), true)
|
||||
actionGroup.templatePresentation.icon = AllIcons.Actions.Show
|
||||
val treeViewRef = WeakReference(treeView)
|
||||
actionGroup.add(FilteringToggleAction(LangBundle.message("build.tree.filters.show.warnings"), WarningsToggleAction.STATE_KEY,
|
||||
BuildTreeView::showingWarnings, WarningsToggleAction.DEFAULT_STATE, treeViewRef))
|
||||
actionGroup.add(FilteringToggleAction(LangBundle.message("build.tree.filters.show.successful"), SuccessfulStepsToggleAction.STATE_KEY,
|
||||
BuildTreeView::showingSuccessful, SuccessfulStepsToggleAction.DEFAULT_STATE, treeViewRef))
|
||||
return actionGroup
|
||||
}
|
||||
}
|
||||
|
||||
private fun restoreSavedFiltering(treeView: BuildTreeView) {
|
||||
treeView.showingWarnings = PropertiesComponent.getInstance().getBoolean(WarningsToggleAction.STATE_KEY,
|
||||
WarningsToggleAction.DEFAULT_STATE)
|
||||
treeView.showingSuccessful = PropertiesComponent.getInstance().getBoolean(SuccessfulStepsToggleAction.STATE_KEY,
|
||||
SuccessfulStepsToggleAction.DEFAULT_STATE)
|
||||
}
|
||||
|
||||
private class FilteringToggleAction(
|
||||
@NlsContexts.Command text: String,
|
||||
private val stateKey: String,
|
||||
private val property: KMutableProperty1<BuildTreeView, Boolean>,
|
||||
private val defaultState: Boolean,
|
||||
private val treeViewRef: Reference<BuildTreeView?>,
|
||||
) : ToggleAction(text), DumbAware {
|
||||
override fun getActionUpdateThread() = ActionUpdateThread.EDT
|
||||
|
||||
override fun isSelected(e: AnActionEvent): Boolean {
|
||||
val presentation = e.presentation
|
||||
val treeView = treeViewRef.get()
|
||||
if (treeView == null) {
|
||||
presentation.isEnabledAndVisible = false
|
||||
return false
|
||||
}
|
||||
presentation.isEnabledAndVisible = true
|
||||
return property.get(treeView)
|
||||
}
|
||||
|
||||
override fun setSelected(e: AnActionEvent, state: Boolean) {
|
||||
val treeView = treeViewRef.get() ?: return
|
||||
property.set(treeView, state)
|
||||
PropertiesComponent.getInstance().setValue(stateKey, state, defaultState)
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,6 @@ import com.intellij.openapi.diagnostic.fileLogger
|
||||
import com.intellij.openapi.project.DumbAwareAction
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.OnePixelDivider
|
||||
import com.intellij.openapi.util.Computable
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.NlsContexts
|
||||
import com.intellij.openapi.wm.ToolWindow
|
||||
@@ -57,14 +56,14 @@ internal class FrontendMultipleBuildsView(
|
||||
private val id = buildContent.id
|
||||
private val name = buildContent.name
|
||||
private val buildMap = mutableMapOf<BuildId, FrontendBuildInfo>()
|
||||
private val viewMap = mutableMapOf<FrontendBuildInfo, BuildView>()
|
||||
private val viewMap = mutableMapOf<FrontendBuildInfo, FrontendBuildView>()
|
||||
private val toolbarActions = DefaultActionGroup()
|
||||
private val threeComponentsSplitter = createSplitter()
|
||||
private val buildListModel = DefaultListModel<FrontendBuildInfo>()
|
||||
private val buildList = createList()
|
||||
private val content: Content = createContent(id, buildContent.isPinned)
|
||||
private val focusWatcher = FocusWatcher()
|
||||
private var activeView: BuildView? = null
|
||||
private var activeView: FrontendBuildView? = null
|
||||
private var locked = false
|
||||
|
||||
init {
|
||||
@@ -165,7 +164,7 @@ internal class FrontendMultipleBuildsView(
|
||||
buildList.setFixedCellHeight(JBUI.scale(UIUtil.LIST_FIXED_CELL_HEIGHT * 2))
|
||||
}
|
||||
|
||||
private fun setActiveView(view: BuildView?) {
|
||||
private fun setActiveView(view: FrontendBuildView?) {
|
||||
if (activeView === view) {
|
||||
return
|
||||
}
|
||||
@@ -176,20 +175,20 @@ internal class FrontendMultipleBuildsView(
|
||||
content.preferredFocusableComponent = null
|
||||
}
|
||||
else {
|
||||
threeComponentsSplitter.secondComponent = view.component
|
||||
content.setPreferredFocusedComponent(Computable { view.preferredFocusableComponent })
|
||||
threeComponentsSplitter.secondComponent = view
|
||||
content.preferredFocusableComponent = view
|
||||
if (focusWatcher.focused) {
|
||||
view.preferredFocusableComponent?.requestFocusInWindow() // todo check IJPL-172285
|
||||
view.requestFocusInWindow() // todo check IJPL-172285
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun configureToolbar(view: BuildView?) {
|
||||
private fun configureToolbar(view: FrontendBuildView?) {
|
||||
toolbarActions.removeAll()
|
||||
if (view != null) {
|
||||
toolbarActions.addAll(*view.createConsoleActions())
|
||||
// todo view-dependent actions
|
||||
toolbarActions.add(PinBuildViewAction())
|
||||
toolbarActions.add(createFilteringActionsGroup(WeakFilterableSupplier(view)))
|
||||
toolbarActions.add(view.createFilteringActionGroup())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,7 +198,7 @@ internal class FrontendMultipleBuildsView(
|
||||
val info = FrontendBuildInfo(event)
|
||||
buildMap[event.buildId] = info
|
||||
buildListModel.addElement(info)
|
||||
val buildView = BuildView(project, info, "build.toolwindow.${name}.selection.state", MyViewManager)
|
||||
val buildView = FrontendBuildView(project, scope, event.treeViewId, event.consoleComponent)
|
||||
viewMap[info] = buildView
|
||||
Disposer.register(this, buildView)
|
||||
if (activeView == null) {
|
||||
@@ -243,10 +242,14 @@ internal class FrontendMultipleBuildsView(
|
||||
is BuildViewEvent.BuildRemoved -> {
|
||||
val info = buildMap.remove(event.buildId) ?: return
|
||||
buildListModel.removeElement(info)
|
||||
Disposer.dispose(viewMap.remove(info)!!)
|
||||
val buildView = viewMap.remove(info)!!
|
||||
Disposer.dispose(buildView)
|
||||
if (buildListModel.size == 1) {
|
||||
setBuildListVisible(false)
|
||||
}
|
||||
if (buildView === activeView) {
|
||||
setActiveView(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -304,10 +307,10 @@ internal class FrontendMultipleBuildsView(
|
||||
val range = if (next) index..<buildListModel.size() else index downTo 0
|
||||
return range.firstNotNullOfOrNull { i ->
|
||||
val buildInfo = buildListModel.getElementAt(i)
|
||||
val buildView: BuildView? = viewMap[buildInfo]
|
||||
val buildView: FrontendBuildView? = viewMap[buildInfo]
|
||||
if (buildView == null) return@firstNotNullOfOrNull null
|
||||
if (i != index) {
|
||||
val eventView = buildView.eventView
|
||||
val eventView = buildView.treeView
|
||||
if (eventView == null) return@firstNotNullOfOrNull null
|
||||
eventView.clearTreeSelection()
|
||||
}
|
||||
@@ -429,9 +432,4 @@ internal class FrontendMultipleBuildsView(
|
||||
|
||||
override fun toString() = "Build[$id/$title]"
|
||||
}
|
||||
|
||||
private object MyViewManager : ViewManager {
|
||||
override fun isConsoleEnabledByDefault() = false
|
||||
override fun isBuildContentView() = true
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
package com.intellij.build
|
||||
|
||||
import com.intellij.build.events.*
|
||||
import com.intellij.ide.rpc.setupTransfer
|
||||
import com.intellij.openapi.diagnostic.debug
|
||||
import com.intellij.openapi.diagnostic.fileLogger
|
||||
import com.intellij.openapi.diagnostic.trace
|
||||
@@ -121,9 +122,13 @@ class BackendMultipleBuildsView(
|
||||
|
||||
buildView.onEvent(buildId, event)
|
||||
|
||||
val treeViewId = buildView.eventView?.buildViewId
|
||||
val consoleComponent = buildView.consoleComponent.setupTransfer(buildView)
|
||||
|
||||
viewManager.onBuildStart(buildInfo)
|
||||
viewModel.onBuildStarted(this, id, buildInfo.title, buildInfo.startTime, event.message,
|
||||
buildInfo.isAutoFocusContent, buildInfo.isActivateToolWindowWhenAdded)
|
||||
buildInfo.isAutoFocusContent, buildInfo.isActivateToolWindowWhenAdded,
|
||||
treeViewId, consoleComponent)
|
||||
}
|
||||
else {
|
||||
if (!isFirstErrorShown &&
|
||||
|
||||
@@ -101,7 +101,10 @@ public final class BuildTreeConsoleView implements ConsoleView, UiDataProvider,
|
||||
public static final DataKey<BuildTreeConsoleView> COMPONENT_KEY = DataKey.create("BuildTreeConsoleView");
|
||||
|
||||
private static final @NonNls String TREE = "tree";
|
||||
private static final @NonNls String SPLITTER_PROPERTY = "BuildView.Splitter.Proportion";
|
||||
@ApiStatus.Internal
|
||||
public static final @NonNls String SPLITTER_PROPERTY = "BuildView.Splitter.Proportion";
|
||||
@ApiStatus.Internal
|
||||
public static final float SPLITTER_DEFAULT_PROPORTION = 0.33f;
|
||||
|
||||
@Service(Service.Level.PROJECT)
|
||||
private static final class ScopeHolder {
|
||||
@@ -140,7 +143,8 @@ public final class BuildTreeConsoleView implements ConsoleView, UiDataProvider,
|
||||
private final OccurenceNavigator myOccurrenceNavigatorSupport;
|
||||
private final Set<BuildEvent> myDeferredEvents = ConcurrentCollectionFactory.createConcurrentSet();
|
||||
|
||||
private final boolean mySplitImplementation = Registry.is("build.toolwindow.split.tree", false);
|
||||
private final boolean mySplitImplementation = Registry.is("build.toolwindow.split.tree", false) ||
|
||||
Registry.is("build.toolwindow.split", false);
|
||||
|
||||
public BuildTreeConsoleView(@NotNull Project project,
|
||||
@NotNull BuildDescriptor buildDescriptor,
|
||||
@@ -204,7 +208,7 @@ public final class BuildTreeConsoleView implements ConsoleView, UiDataProvider,
|
||||
}
|
||||
|
||||
myPanel.setLayout(new BorderLayout());
|
||||
OnePixelSplitter myThreeComponentsSplitter = new OnePixelSplitter(SPLITTER_PROPERTY, 0.33f);
|
||||
OnePixelSplitter myThreeComponentsSplitter = new OnePixelSplitter(SPLITTER_PROPERTY, SPLITTER_DEFAULT_PROPORTION);
|
||||
myThreeComponentsSplitter.setFirstComponent(treeComponent);
|
||||
List<Filter> filters = myBuildDescriptor.getExecutionFilters();
|
||||
myConsoleViewHandler = new ConsoleViewHandler(myProject, myTree, myBuildProgressRootNode, this,
|
||||
@@ -1119,6 +1123,15 @@ public final class BuildTreeConsoleView implements ConsoleView, UiDataProvider,
|
||||
myConsoleViewHandler.setNodeIfChanged(node);
|
||||
}
|
||||
|
||||
BuildViewId getBuildViewId() {
|
||||
return mySplitImplementation ? myTreeVm.getId() : null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
JComponent getConsoleComponent() {
|
||||
return myConsoleViewHandler.getComponent();
|
||||
}
|
||||
|
||||
private static final class ConsoleViewHandler implements Disposable {
|
||||
private static final String EMPTY_CONSOLE_NAME = "empty";
|
||||
private final Project myProject;
|
||||
|
||||
@@ -245,6 +245,19 @@ public class BuildView extends CompositeView<ExecutionConsole>
|
||||
return getView(BuildTreeConsoleView.class.getName(), BuildTreeConsoleView.class);
|
||||
}
|
||||
|
||||
// returns a non-null value after the view is initialized (after build start event is processed)
|
||||
JComponent getConsoleComponent() {
|
||||
BuildTreeConsoleView eventView = getEventView();
|
||||
if (eventView != null) {
|
||||
return eventView.getConsoleComponent();
|
||||
}
|
||||
ExecutionConsole console = getView(CONSOLE_VIEW_NAME);
|
||||
if (console != null) {
|
||||
return console.getComponent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addChangeListener(@NotNull ChangeListener listener, @NotNull Disposable parent) {
|
||||
ExecutionConsole console = getConsoleView();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
package com.intellij.build
|
||||
|
||||
import com.intellij.build.events.BuildEventsNls
|
||||
import com.intellij.ide.rpc.ComponentDirectTransferId
|
||||
import com.intellij.ide.ui.icons.IconId
|
||||
import com.intellij.openapi.util.NlsContexts
|
||||
import com.intellij.platform.rpc.Id
|
||||
@@ -23,6 +24,8 @@ sealed interface BuildViewEvent {
|
||||
val message: @BuildEventsNls.Message String,
|
||||
val requestFocus: Boolean,
|
||||
val activateToolWindow: Boolean,
|
||||
val treeViewId: BuildViewId?,
|
||||
val consoleComponent: ComponentDirectTransferId,
|
||||
) : BuildViewEvent
|
||||
|
||||
@Serializable
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
package com.intellij.build
|
||||
|
||||
import com.intellij.build.events.BuildEventsNls
|
||||
import com.intellij.ide.rpc.ComponentDirectTransferId
|
||||
import com.intellij.ide.ui.icons.rpcId
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.components.service
|
||||
@@ -27,10 +28,13 @@ class BuildViewViewModel(scope: CoroutineScope) : FlowWithHistory<BuildViewEvent
|
||||
message: @BuildEventsNls.Message String,
|
||||
requestFocus: Boolean,
|
||||
activateToolWindow: Boolean,
|
||||
treeViewId: BuildViewId?,
|
||||
consoleComponent: ComponentDirectTransferId,
|
||||
) {
|
||||
updateHistoryAndEmit {
|
||||
val viewState = viewStates.computeIfAbsent(view) { ViewState() }
|
||||
BuildViewEvent.BuildStarted(view.toDto(), buildId, title, startTime, message, requestFocus, activateToolWindow).also {
|
||||
BuildViewEvent.BuildStarted(view.toDto(), buildId, title, startTime, message, requestFocus, activateToolWindow,
|
||||
treeViewId, consoleComponent).also {
|
||||
viewState.buildMap[buildId] = BuildState(it.copy(requestFocus = false, activateToolWindow = false))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,8 @@ internal fun install(filterable: Filterable<ExecutionNode>) {
|
||||
WarningsToggleAction.install(filterable)
|
||||
}
|
||||
|
||||
internal open class FilterToggleAction(
|
||||
@ApiStatus.Internal
|
||||
open class FilterToggleAction(
|
||||
@NlsContexts.Command text: String,
|
||||
private val stateKey: String?,
|
||||
private val filterableRef: Supplier<Filterable<ExecutionNode>?>,
|
||||
@@ -100,26 +101,36 @@ private fun install(
|
||||
}
|
||||
}
|
||||
|
||||
internal class SuccessfulStepsToggleAction(filterable: Supplier<Filterable<ExecutionNode>?>) :
|
||||
FilterToggleAction(LangBundle.message("build.tree.filters.show.successful"), STATE_KEY, filterable, SUCCESSFUL_STEPS_FILTER, false), DumbAware {
|
||||
@ApiStatus.Internal
|
||||
class SuccessfulStepsToggleAction(filterable: Supplier<Filterable<ExecutionNode>?>) :
|
||||
FilterToggleAction(LangBundle.message("build.tree.filters.show.successful"),
|
||||
STATE_KEY, filterable, SUCCESSFUL_STEPS_FILTER, DEFAULT_STATE), DumbAware {
|
||||
|
||||
companion object {
|
||||
private const val STATE_KEY = "build.toolwindow.show.successful.steps.selection.state"
|
||||
@ApiStatus.Internal
|
||||
const val STATE_KEY: String = "build.toolwindow.show.successful.steps.selection.state"
|
||||
@ApiStatus.Internal
|
||||
const val DEFAULT_STATE: Boolean = false
|
||||
|
||||
fun install(filterable: Filterable<ExecutionNode>) {
|
||||
install(filterable, SUCCESSFUL_STEPS_FILTER, STATE_KEY, false)
|
||||
install(filterable, SUCCESSFUL_STEPS_FILTER, STATE_KEY, DEFAULT_STATE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class WarningsToggleAction(filterable: Supplier<Filterable<ExecutionNode>?>) :
|
||||
FilterToggleAction(LangBundle.message("build.tree.filters.show.warnings"), STATE_KEY, filterable, WARNINGS_FILTER, true), DumbAware {
|
||||
@ApiStatus.Internal
|
||||
class WarningsToggleAction(filterable: Supplier<Filterable<ExecutionNode>?>) :
|
||||
FilterToggleAction(LangBundle.message("build.tree.filters.show.warnings"),
|
||||
STATE_KEY, filterable, WARNINGS_FILTER, DEFAULT_STATE), DumbAware {
|
||||
|
||||
companion object {
|
||||
private const val STATE_KEY = "build.toolwindow.show.warnings.selection.state"
|
||||
@ApiStatus.Internal
|
||||
const val STATE_KEY: String = "build.toolwindow.show.warnings.selection.state"
|
||||
@ApiStatus.Internal
|
||||
const val DEFAULT_STATE: Boolean = true
|
||||
|
||||
fun install(filterable: Filterable<ExecutionNode>) {
|
||||
install(filterable, WARNINGS_FILTER, STATE_KEY, true)
|
||||
install(filterable, WARNINGS_FILTER, STATE_KEY, DEFAULT_STATE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user