/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.execution.dashboard;
import com.intellij.ide.util.treeView.AbstractTreeBuilder;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author konstantin.aleev
*/
public abstract class DashboardTreeAction<T, C extends TreeContent> extends AnAction {
protected DashboardTreeAction(String text, String description, Icon icon) {
super(text, description, icon);
}
@Override
public void update(@NotNull AnActionEvent e) {
Presentation presentation = e.getPresentation();
List<T> targetNodes = getTargetNodes(e);
boolean visible = isVisibleForAnySelection(e) || (!targetNodes.isEmpty() && targetNodes.stream().allMatch(this::isVisible4));
boolean enabled = visible && (!targetNodes.isEmpty() && targetNodes.stream().allMatch(this::isEnabled4));
presentation.setVisible(visible);
presentation.setEnabled(enabled);
updatePresentation(presentation, ContainerUtil.getFirstItem(targetNodes));
}
/**
* Invokes {@link #collectNodes(AbstractTreeBuilder) collectNodes()} to collect nodes.
* If each collected node could be casted to tree action node class,
* returns a list of collected nodes casted to tree action node class, otherwise returns empty list.
*
* @param e Action event.
* @return List of target nodes for this action.
*/
@NotNull
protected List<T> getTargetNodes(AnActionEvent e) {
C content = getTreeContent(e);
if (content == null) {
return Collections.emptyList();
}
Set<?> selectedElements = collectNodes(content.getBuilder());
int selectionCount = selectedElements.size();
if (selectionCount == 0 || selectionCount > 1 && !isMultiSelectionAllowed()) {
return Collections.emptyList();
}
Class<T> targetNodeClass = getTargetNodeClass();
List<T> result = new ArrayList<>();
for (Object selectedElement : selectedElements) {
if (!targetNodeClass.isInstance(selectedElement)) {
return Collections.emptyList();
}
result.add(targetNodeClass.cast(selectedElement));
}
return result;
}
/**
* This implementation returns a set of selected nodes.
* Subclasses may override this method to return modified nodes set.
*
* @param treeBuilder Tree builder.
* @return Set of tree nodes for which action should be performed.
*/
@NotNull
protected Set<?> collectNodes(@NotNull AbstractTreeBuilder treeBuilder) {
return treeBuilder.getSelectedElements();
}
protected abstract C getTreeContent(AnActionEvent e);
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
List<T> verifiedTargetNodes = getTargetNodes(e).stream().filter(node -> isVisible4(node) && isEnabled4(node))
.collect(Collectors.toList());
doActionPerformed(getTreeContent(e), e, verifiedTargetNodes);
}
protected boolean isVisibleForAnySelection(@NotNull AnActionEvent e) {
return false;
}
protected boolean isMultiSelectionAllowed() {
return false;
}
protected boolean isVisible4(T node) {
return true;
}
protected boolean isEnabled4(T node) {
return true;
}
protected void updatePresentation(@NotNull Presentation presentation, @Nullable T node) {
}
protected void doActionPerformed(@NotNull C content, AnActionEvent e, List<T> nodes) {
nodes.forEach(node -> doActionPerformed(content, e , node));
}
protected void doActionPerformed(@NotNull C content, AnActionEvent e, T node) {
doActionPerformed(node);
}
protected void doActionPerformed(T node) {
throw new UnsupportedOperationException();
}
protected abstract Class<T> getTargetNodeClass();
}