mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-03-22 15:19:59 +07:00
avoid calling actions update during the main menu calculation 2
In RemDev, the host updates menu groups directly without the enclosing `IdeMainMenuActionGroup` group. Its `ALWAYS_VISIBLE` setting is ignored. The solution is to use `ActionConfigurationCustomizer` that works both on client and host. Also, we now copy client properties from stub presentation to its action template presentation. See `Presentation.copyUnsetTemplateProperties`. GitOrigin-RevId: 153d76dc7a3d97e7355bad3236b7ca09b244d0e3
This commit is contained in:
committed by
intellij-monorepo-bot
parent
03ee822772
commit
d21dad3611
@@ -120,7 +120,8 @@ public abstract class AnAction implements PossiblyDumbAware, ActionUpdateThreadA
|
||||
* @param icon the action's icon
|
||||
*/
|
||||
public AnAction(@Nullable @ActionText String text, @Nullable @ActionDescription String description, @Nullable Icon icon) {
|
||||
this(() -> text, () -> description, icon);
|
||||
this(text == null ? Presentation.NULL_STRING : () -> text,
|
||||
description == null ? Presentation.NULL_STRING : () -> description, icon);
|
||||
}
|
||||
|
||||
@ApiStatus.Experimental
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.NotNullLazyValue;
|
||||
import com.intellij.openapi.util.SystemInfoRt;
|
||||
import com.intellij.openapi.util.text.Strings;
|
||||
import com.intellij.openapi.util.text.TextWithMnemonic;
|
||||
import com.intellij.util.BitUtil;
|
||||
import com.intellij.util.SmartFMap;
|
||||
@@ -36,6 +37,7 @@ public final class Presentation implements Cloneable {
|
||||
private static final Logger LOG = Logger.getInstance(Presentation.class);
|
||||
|
||||
public static final Supplier<String> NULL_STRING = () -> null;
|
||||
public static final Supplier<TextWithMnemonic> NULL_TEXT_WITH_MNEMONIC = () -> null;
|
||||
|
||||
// Property keys for the PropertyChangeListener API
|
||||
public static final @NonNls String PROP_TEXT = "text";
|
||||
@@ -71,7 +73,7 @@ public final class Presentation implements Cloneable {
|
||||
|
||||
private int myFlags = IS_ENABLED | IS_VISIBLE | IS_DISABLE_GROUP_IF_EMPTY;
|
||||
private @NotNull Supplier<@ActionDescription String> descriptionSupplier = NULL_STRING;
|
||||
private @NotNull Supplier<TextWithMnemonic> textWithMnemonicSupplier = () -> null;
|
||||
private @NotNull Supplier<TextWithMnemonic> textWithMnemonicSupplier = NULL_TEXT_WITH_MNEMONIC;
|
||||
private @NotNull SmartFMap<String, Object> myUserMap = SmartFMap.emptyMap();
|
||||
|
||||
private @Nullable Supplier<? extends @Nullable Icon> icon;
|
||||
@@ -169,7 +171,10 @@ public final class Presentation implements Cloneable {
|
||||
|
||||
public @NotNull Supplier<TextWithMnemonic> getTextWithMnemonic(@NotNull Supplier<@Nls(capitalization = Nls.Capitalization.Title) String> text,
|
||||
boolean mayContainMnemonic) {
|
||||
if (mayContainMnemonic) {
|
||||
if (text == NULL_STRING) {
|
||||
return NULL_TEXT_WITH_MNEMONIC;
|
||||
}
|
||||
else if (mayContainMnemonic) {
|
||||
return () -> {
|
||||
String s = text.get();
|
||||
if (s == null) {
|
||||
@@ -283,10 +288,18 @@ public final class Presentation implements Cloneable {
|
||||
return icon;
|
||||
}
|
||||
|
||||
public void copyIconIfUnset(@NotNull Presentation other) {
|
||||
if (icon == null && other.icon != null) {
|
||||
@ApiStatus.Internal // do not expose
|
||||
void copyUnsetTemplateProperties(@NotNull Presentation other) {
|
||||
if (icon == null) {
|
||||
icon = other.icon;
|
||||
}
|
||||
if (Strings.isEmpty(getText()) && Strings.isNotEmpty(other.getText())) {
|
||||
textWithMnemonicSupplier = other.textWithMnemonicSupplier;
|
||||
}
|
||||
if (Strings.isEmpty(descriptionSupplier.get()) && Strings.isNotEmpty(other.descriptionSupplier.get())) {
|
||||
descriptionSupplier = other.descriptionSupplier;
|
||||
}
|
||||
myUserMap = myUserMap.plusAll(other.myUserMap);
|
||||
}
|
||||
|
||||
public void setIcon(@Nullable Icon icon) {
|
||||
|
||||
@@ -4,7 +4,6 @@ package com.intellij.openapi.actionSystem;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.PluginDescriptor;
|
||||
import com.intellij.openapi.project.ProjectType;
|
||||
import com.intellij.openapi.util.text.Strings;
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -105,13 +104,10 @@ public final class ActionStub extends AnAction implements ActionStubBase {
|
||||
}
|
||||
}
|
||||
|
||||
public static void copyTemplatePresentation(Presentation sourcePresentation, Presentation targetPresentation) {
|
||||
targetPresentation.copyIconIfUnset(sourcePresentation);
|
||||
if (Strings.isEmpty(targetPresentation.getText()) && sourcePresentation.getText() != null) {
|
||||
targetPresentation.setTextWithMnemonic(sourcePresentation.getTextWithPossibleMnemonic());
|
||||
}
|
||||
if (targetPresentation.getDescription() == null && sourcePresentation.getDescription() != null) {
|
||||
targetPresentation.setDescription(sourcePresentation.getDescription());
|
||||
}
|
||||
public static void copyTemplatePresentation(@NotNull Presentation sourcePresentation,
|
||||
@NotNull Presentation targetPresentation) {
|
||||
// Note: actions can update templatePresentation in constructor.
|
||||
// We apply stub properties only after that. It could be confusing.
|
||||
targetPresentation.copyUnsetTemplateProperties(sourcePresentation);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,11 @@ internal class ActionGroupStub(override val id: String,
|
||||
|
||||
fun initGroup(target: ActionGroup, actionToId: Function<AnAction, String?>) {
|
||||
ActionStub.copyTemplatePresentation(templatePresentation, target.templatePresentation)
|
||||
if (popupDefinedInXml) target.isPopup = isPopup
|
||||
|
||||
copyActionTextOverrides(target)
|
||||
|
||||
target.isSearchable = isSearchable
|
||||
target.shortcutSet = shortcutSet
|
||||
val children = childActionsOrStubs
|
||||
if (children.isNotEmpty()) {
|
||||
@@ -29,9 +32,5 @@ internal class ActionGroupStub(override val id: String,
|
||||
target.addAction(action, Constraints.LAST, actionToId)
|
||||
}
|
||||
}
|
||||
if (popupDefinedInXml) {
|
||||
target.isPopup = isPopup
|
||||
}
|
||||
target.isSearchable = isSearchable
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.intellij.ide.ui.UISettingsListener
|
||||
import com.intellij.ide.ui.customization.CustomActionsSchema
|
||||
import com.intellij.openapi.actionSystem.*
|
||||
import com.intellij.openapi.actionSystem.ex.ActionManagerEx
|
||||
import com.intellij.openapi.actionSystem.ex.ActionRuntimeRegistrar
|
||||
import com.intellij.openapi.actionSystem.impl.*
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.EDT
|
||||
@@ -188,17 +189,22 @@ private suspend fun expandMainActionGroup(mainActionGroup: ActionGroup,
|
||||
@ApiStatus.Internal
|
||||
suspend fun IdeMainMenuActionGroup(): ActionGroup? {
|
||||
val group = CustomActionsSchema.getInstanceAsync().getCorrectedActionAsync(IdeActions.GROUP_MAIN_MENU) ?: return null
|
||||
// enforce the "always-visible" flag for all main menu items
|
||||
// without forcing everyone to employ custom groups in their plugin.xml files.
|
||||
return object : ActionGroupWrapper(group) {
|
||||
override fun getChildren(e: AnActionEvent?): Array<out AnAction> {
|
||||
return super.getChildren(e).onEach { it.templatePresentation.putClientProperty(ActionMenu.ALWAYS_VISIBLE, true) }
|
||||
}
|
||||
|
||||
override fun postProcessVisibleChildren(visibleChildren: List<AnAction>,
|
||||
updateSession: UpdateSession): List<AnAction?> {
|
||||
return super.postProcessVisibleChildren(visibleChildren, updateSession)
|
||||
.filterIsInstance<ActionGroup>()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class IdeMainMenuActionCustomizer : ActionConfigurationCustomizer, ActionConfigurationCustomizer.LightCustomizeStrategy {
|
||||
// enforce the "always-visible" flag for all main menu items
|
||||
// without forcing everyone to employ custom groups in their plugin.xml files.
|
||||
override suspend fun customize(actionRegistrar: ActionRuntimeRegistrar) {
|
||||
val group = actionRegistrar.getActionOrStub(IdeActions.GROUP_MAIN_MENU) as? DefaultActionGroup
|
||||
group?.childActionsOrStubs?.forEach {
|
||||
it.templatePresentation.putClientProperty(ActionMenu.ALWAYS_VISIBLE, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1383,6 +1383,7 @@
|
||||
<environmentKeyProvider implementation="com.intellij.ide.plugins.PluginEnvironmentKeyProvider"/>
|
||||
|
||||
|
||||
<actionConfigurationCustomizer implementation="com.intellij.platform.ide.menu.IdeMainMenuActionCustomizer"/>
|
||||
<actionConfigurationCustomizer implementation="com.intellij.platform.ide.menu.GlobalMenuLinux$MyActionTuner"/>
|
||||
|
||||
<titleInfoProvider implementation="com.intellij.openapi.wm.impl.simpleTitleParts.ProductTitleInfoProvider"/>
|
||||
|
||||
Reference in New Issue
Block a user