From 2dcd51d91eb2fa9e9d593365f7fe377b64fbd32c Mon Sep 17 00:00:00 2001 From: nik Date: Fri, 1 Mar 2019 16:58:26 +0300 Subject: [PATCH] actions: reimplement logic used to determine whether 'New Scratch File' action is shown in 'New' submenu Previously it was checked via 'PlatformOpenProjectGroup' action group, but this group may not be added in all IDEs, so the check didn't work properly e.g. for Rider. Now it's checked in a more straightforward and reliable way by inspecting 'New' group. NewActionGroup.isActionInNewPopupMenu method is needed to do a similar thing for other actions which are located in 'New' submenu in IDEA but will be shown directly in 'File' menu for other IDEs with Java plugin (IDEA-195719). --- .../intellij/ide/actions/NewActionGroup.java | 11 ++++++++ .../ide/scratch/ScratchFileActions.java | 27 ++++++++----------- .../openapi/actionSystem/ex/ActionUtil.java | 15 ++++++++--- 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/actions/NewActionGroup.java b/platform/lang-impl/src/com/intellij/ide/actions/NewActionGroup.java index c369373489d6..a2fddc7bde72 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/NewActionGroup.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/NewActionGroup.java @@ -16,12 +16,14 @@ package com.intellij.ide.actions; import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.actionSystem.ex.ActionUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.function.Predicate; /** * @author Dmitry Avdeev @@ -47,4 +49,13 @@ public class NewActionGroup extends ActionGroup { } return actions; } + + public static boolean isActionInNewPopupMenu(@NotNull AnAction action) { + ActionManager actionManager = ActionManager.getInstance(); + ActionGroup fileGroup = (ActionGroup)actionManager.getAction(IdeActions.GROUP_FILE); + if (!ActionUtil.anyActionFromGroupMatches(fileGroup, false, child -> child instanceof NewActionGroup)) return false; + + ActionGroup newGroup = (ActionGroup)actionManager.getAction(IdeActions.GROUP_NEW); + return ActionUtil.anyActionFromGroupMatches(newGroup, false, Predicate.isEqual(action)); + } } diff --git a/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileActions.java b/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileActions.java index a472cf9a1082..821b07100796 100644 --- a/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileActions.java +++ b/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileActions.java @@ -3,6 +3,7 @@ package com.intellij.ide.scratch; import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.icons.AllIcons; +import com.intellij.ide.actions.NewActionGroup; import com.intellij.ide.util.PsiNavigationSupport; import com.intellij.idea.ActionsBundle; import com.intellij.lang.Language; @@ -55,19 +56,15 @@ public class ScratchFileActions { private static final String ACTION_ID = "NewScratchFile"; - private static final String SMALLER_IDE_CONTAINER_GROUP = "PlatformOpenProjectGroup"; - - private final String myActionText; + private String myActionText; public NewFileAction() { getTemplatePresentation().setIcon(ICON); - // A hacky way for customizing text in IDEs without File->New-> submenu - myActionText = (isIdeWithoutNewSubmenu() ? "New " : "") + ActionsBundle.actionText(ACTION_ID); } @Override public void update(@NotNull AnActionEvent e) { - getTemplatePresentation().setText(myActionText); + getTemplatePresentation().setText(getActionText()); Project project = e.getProject(); String place = e.getPlace(); @@ -101,20 +98,18 @@ public class ScratchFileActions { } private void updatePresentationTextAndIcon(@NotNull AnActionEvent e, @NotNull Presentation presentation) { - presentation.setText(myActionText); + presentation.setText(getActionText()); presentation.setIcon(ICON); - if (ActionPlaces.MAIN_MENU.equals(e.getPlace())) { - if (isIdeWithoutNewSubmenu()) { - presentation.setIcon(null); - } + if (ActionPlaces.MAIN_MENU.equals(e.getPlace()) && !NewActionGroup.isActionInNewPopupMenu(this)) { + presentation.setIcon(null); } } - private boolean isIdeWithoutNewSubmenu() { - if (PlatformUtils.isRider()) return true; - final AnAction group = ActionManager.getInstance().getActionOrStub(SMALLER_IDE_CONTAINER_GROUP); - return group instanceof DefaultActionGroup && ContainerUtil.find(((DefaultActionGroup)group).getChildActionsOrStubs(), action -> - action == this || (action instanceof ActionStub && ((ActionStub)action).getId().equals(ACTION_ID))) != null; + private String getActionText() { + if (myActionText == null) { + myActionText = (NewActionGroup.isActionInNewPopupMenu(this) ? "" : "New ") + ActionsBundle.actionText(ACTION_ID); + } + return myActionText; } } diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ActionUtil.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ActionUtil.java index bf8792b2df0a..453e5970b869 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ActionUtil.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ActionUtil.java @@ -43,6 +43,7 @@ import java.awt.event.InputEvent; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.function.Predicate; public class ActionUtil { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.actionSystem.ex.ActionUtil"); @@ -325,10 +326,18 @@ public class ActionUtil { } public static boolean recursiveContainsAction(@NotNull ActionGroup group, @NotNull AnAction action) { + return anyActionFromGroupMatches(group, true, Predicate.isEqual(action)); + } + + public static boolean anyActionFromGroupMatches(@NotNull ActionGroup group, boolean processPopupSubGroups, + @NotNull Predicate condition) { for (AnAction child : group.getChildren(null)) { - if (action.equals(child)) return true; - if (child instanceof ActionGroup && recursiveContainsAction((ActionGroup)child, action)) { - return true; + if (condition.test(child)) return true; + if (child instanceof ActionGroup) { + ActionGroup childGroup = (ActionGroup)child; + if ((processPopupSubGroups || !childGroup.isPopup()) && anyActionFromGroupMatches(childGroup, processPopupSubGroups, condition)) { + return true; + } } } return false;