Add a Menu Item to the IntelliJ App
I have been adding a menu item to the IntelliJ Code menu at startup for years. With each new version it gets harder. Why? This should be simple and easy. I do not want to do this after a project is loaded; I want to do this just once at startup. I want to do it in Java, not Kotlin. What is the problem, JetBrains? You are making this more and more complicated. This should be simple!
My current approach is to override AppLifecycleListener. appStarted() But now that method is marked @ApiStatus.Internal
My current code is:
public final class AddLinesOfCodeMenuItem
implements AppLifecycleListener
{
private static final String JAVA_LINES_OF_CODE = "JavaLinesOfCode";
@Override
public void appStarted()
{
AnAction countLinesOfCode = new CountLinesOfCode();
ActionManager actionManager = ActionManager.getInstance();
actionManager.registerAction(JAVA_LINES_OF_CODE,
countLinesOfCode);
DefaultActionGroup codeMenu = (DefaultActionGroup)
actionManager.getAction("CodeMenu");
assert codeMenu != null : "Failed to get: CodeMenu";
codeMenu.add(countLinesOfCode, Constraints.LAST);
}
}
Please sign in to leave a comment.
Why do you use programmatic registration? From the problem description I supposed that `appStarted` event does not guarantee all IDE menus are already registered.
It would be simpler to register actions via plugin.xml https://plugins.jetbrains.com/docs/intellij/basic-action-system.html#registering-actions.
First, thank you for responding. I respect the time it takes for you to do this.
I respectfully disagree that “it would be simpler to register actions …”.
I prefer to use Java rather than edit configuration files, especially when I am told to specify concrete class names in the configuration file. This couples the code to the configuration file. The configuration file becomes an extension of the code. If I change the code, I now may have to change the configuration file. I have to understand all the syntax of XML in addition to Java and the specific syntax of the configuration file. I want the Java source to be as decoupled as possible from configuration files.
I am following the suggested pattern for specifying actions using code on the web page you sent me to. It used to work. Why does it not work now? Why have the Jetbrains developers marked the method AppLifecycleListener.appStarted with @ApiStatus.Internal ?
The user interface should be stable. Menu items should not appear and disappear under conditions not obvious to the user. If an item is not currently usable, it should be disabled (greyed out), but *not* removed. When the IntelliJ IDEA app comes up, my plugin menu items should appear and remain until the app shuts down. I do *not* want them to be dynamic. That is poor user interface!
What do you mean that all the IDE menus might not be registered when appStarted is called? What else would “app started” mean other than all of the standard IntelliJ IDEA user interface elements are registered and ready to go? I want to add my plugin user interface elements after IntelliJ has fully initialized itself. I want to do this once at startup. The user should not even be aware this has happened. The IntelliJ app just comes up with additional capability.
Please excuse the long delay.
Plugin DevKit provides all necessary tooling to deal with XML registration vs. Code, e.g., gutter icons, inspections, etc.
Regarding marking
AppLifecycleListener.appStarted()
internal API, see the javadocPlugins must use {@link com.intellij.openapi.startup.ProjectActivity} and track successful once-per-application run instead.
“appStarted” lifecycle status means (again from javadoc):
Called after all application startup tasks, including opening projects, are processed (i.e., either completed or running in the background).
So it is indeed expected behaviour that the IDE (incl. UI) is not fully initialized and working.