API addition proposal -- Add Action enum and methods to javafx.application.Application

David Kopp codebangusllc at gmail.com
Tue Oct 15 00:29:03 UTC 2024


I have looked into the Desktop API implementation in the JDK. They have their own code to manipulate the Application menu, so I don’t think it will be possible to get the About and Settings menu items to show up via the Desktop API. I tried the code you had posted in your last email, but the menu items remain absent.

I did try out the other Desktop methods in a little JavaFX test app. Calling them via SwingUtilities.invokeLater works just fine.

So, I think we will need a new, small API in order for JavaFX macOS applications to be able to integrate into the system like Swing apps can.

I currently have:

Added to ConditionalFeature

    /**
     * Indicates whether or not the platform supports an OS application menu About item.
     * <p>
     * Currently, only MacOS support this feature.
     * @since JavaFX 24.0
     */
    ABOUT,

    /**
     * Indicates whether or not the platform supports an OS application menu Settings item.
     * <p>
     * Currently, only MacOS support this feature.
     * @since JavaFX 24.0
     */
    SETTINGS


javafx.application.Application


    /**
     * Installs a handler to show a custom about window for your application.
     * <p>
     * Setting the handler to null reverts it to the default behavior. This is a no-op on
     * platforms that do not support javafx.application.ConditionalFeature.ABOUT
     *
     * @param handler the handler
     *
     * @since JavaFX 24.0
     */
    public void setAboutHandler(Runnable handler) {
        PlatformImpl.setAboutHandler(handler);
    }

    /**
     * Installs a handler to show a custom settings window for your application.
     * <p>
     * Setting the handler to null reverts it to the default behavior. This is a no-op on
     * platforms that do not support javafx.application.ConditionalFeature.SETTINGS
     *
     * @param handler the handler
     *
     * @since JavaFX 24.0
     */
    public void setSettingsHandler(Runnable handler) {
        PlatformImpl.setSettingsHandler(handler);
    }

PlatformImpl.java

    /**
     * Installs a handler to show a custom about window for your application. This is a no-op on
     * platforms that do not support this feature.
     *
     * @since JavaFX 24
     */
    public static void setAboutHandler(Runnable handler) {
        com.sun.glass.ui.Application.GetApplication().setAboutHandler(handler);
    }

    /**
     * Installs a handler to show a custom settings window for your application. This is a no-op on
     * platforms that do not support this feature.
     *
     * @since JavaFX 24
     */
    public static void setSettingsHandler(Runnable handler) {
        com.sun.glass.ui.Application.GetApplication().setSettingsHandler(handler);
    }


com.sun.class.ui.Application

    /**
     * Installs a handler to show a custom About window for your application. This default
     * implementation is a no-op.
     */
    public void setAboutHandler(Runnable handler) {
    }

    /**
     * Installs a handler to show a custom Settings window for your application. This default
     * implementation is a no-op.
     */
    public void setSettingsHandler(Runnable handler) {
    }


MacApplication

    private Runnable aboutHandler;
    private Runnable settingsHandler;

    @Override
    public void setAboutHandler(Runnable handler) {
        aboutHandler = handler;
        rebuildAppleMenu();
    }

    @Override
    public void setSettingsHandler(Runnable handler) {
        settingsHandler = handler;
        rebuildAppleMenu();
    }

    private void rebuildAppleMenu() {
        for (int index = this.appleMenu.getItems().size() - 1; index >= 0; index--) {
            this.appleMenu.remove(index);
        }

        if (null != aboutHandler) {
            MenuItem aboutMenu = createMenuItem("About " + getName(), new MenuItem.Callback() {
                @Override public void action() {
                    aboutHandler.run();
                }
                @Override public void validate() {
                }
            });
            this.appleMenu.add(aboutMenu);
            this.appleMenu.add(MenuItem.Separator);
        }

        if (null != settingsHandler) {
            MenuItem preferencesMenu = createMenuItem("Settings...", new MenuItem.Callback() {
                @Override public void action() {
                  settingsHandler.run();
                }
                @Override public void validate() {
                }
            }, ',', KeyEvent.MODIFIER_COMMAND);
            this.appleMenu.add(preferencesMenu);
            this.appleMenu.add(MenuItem.Separator);
        }

        MenuItem hideMenu = createMenuItem("Hide " + getName(), new MenuItem.Callback() {
            @Override public void action() {
                MacApplication.this._hide();
            }
            @Override public void validate() {
            }
        }, 'h', KeyEvent.MODIFIER_COMMAND);
        this.appleMenu.add(hideMenu);

        MenuItem hideOthersMenu = createMenuItem("Hide Others", new MenuItem.Callback() {
            @Override public void action() {
                MacApplication.this._hideOtherApplications();
            }
            @Override public void validate() {
            }
        }, 'h', KeyEvent.MODIFIER_COMMAND | KeyEvent.MODIFIER_ALT);
        this.appleMenu.add(hideOthersMenu);

        MenuItem unhideAllMenu = createMenuItem("Show All", new MenuItem.Callback() {
            @Override public void action() {
                MacApplication.this._unhideAllApplications();
            }
            @Override public void validate() {
            }
        });
        this.appleMenu.add(unhideAllMenu);

        this.appleMenu.add(MenuItem.Separator);

        MenuItem quitMenu = createMenuItem("Quit " + getName(), new MenuItem.Callback() {
            @Override public void action() {
                Application.EventHandler eh = getEventHandler();
                if (eh != null) {
                    eh.handleQuitAction(Application.GetApplication(), System.nanoTime());
                }
            }
            @Override public void validate() {
            }
        }, 'q', KeyEvent.MODIFIER_COMMAND);
        this.appleMenu.add(quitMenu);
    }

    public void installAppleMenu(MenuBar menubar) {
        this.appleMenu = createMenu("Apple");

        rebuildAppleMenu();

        menubar.add(this.appleMenu);
    }



More information about the openjfx-dev mailing list