How to create a menu action with an icon that toggles?

Post here questions and problems related to oXygen frameworks/document types.
gc_swilson39
Posts: 5
Joined: Wed Feb 19, 2025 7:35 pm

How to create a menu action with an icon that toggles?

Post by gc_swilson39 »

I'm working on a combination workspace access plugin + custom document framework in the desktop version of Oxygen.
I have a custom action I'd like to put in the framework menu, and I want it to toggle an option on/off to control some behavior in my plugin (enable/disable event handlers that respond to DOM changes and try to keep various numbered elements up-to-date). Some users may prefer to only run the numbering updates on-demand, instead of automatically as they make changes to the document. So I want to store the state of this button in options using PluginWorkspace.getOptionsStorage().setOption(key, value).

I have the action defined in a java class, and it is added to the menu using the the my_doctype.framework XML script. In the action's doOperation method, I can read the current option state, flip it, store it back to options, and then set the action button icon accordingly (OptionsManager and ImageResolver are some utility classes I've created):

Code: Select all

public void doOperation(final AuthorAccess authorAccess, final ArgumentsMap args) throws IllegalArgumentException, AuthorOperationException {
  boolean newAutonumberState = !OptionsManager.getBooleanValue(OptionsManager.AUTONUMBERING_ENABLED_KEY);
  AuthorActionsProvider actionsProvider = authorAccess.getEditorAccess().getActionsProvider();
  Map<String, Object> actionMap = actionsProvider.getAuthorExtensionActions();
  Action action = (Action) actionMap.get(AUTONUMBER_ACTION_ID);
  if (action != null) {
    String iconPath = (newAutonumberState ? ImageResolver.AUTONUMBER_ENABLED_ICON : ImageResolver.AUTONUMBER_DISABLED_ICON);
    action.putValue(Action.SMALL_ICON, ImageResolver.getImage(iconPath));
  }
}
This part works AFTER clicking on the menu action one or more times. My problem is that I can't set the icon for the first time whenever a new editor window is opened. I have similar code in my main WorkspaceAccessPluginExtension, inside a WSEditorChangeListener for the editorPageChanged and editorOpened events, and while it doesn't throw any errors, it also doesn't change the icon on the framework menu item:

Code: Select all

public void editorOpened(URL url) {
  WSEditor editorAccess = pluginWorkspaceAccess.getCurrentEditorAccess(StandalonePluginWorkspace.MAIN_EDITING_AREA);
  if (editorAccess.getCurrentPageID().equals(EditorPageConstants.PAGE_AUTHOR)) {
    WSEditorPage editorPage = editorAccess.getCurrentPage();
    if (editorPage instanceof WSAuthorEditorPage authorPage) {
      boolean autonumberState = !OptionsManager.getBooleanValue(OptionsManager.AUTONUMBERING_ENABLED_KEY);
      AuthorActionsProvider actionsProvider = authorPage.getActionsProvider();
      Map<String, Object> actionMap = actionsProvider.getAuthorExtensionActions();
      Action action = (Action) actionMap.get(AUTONUMBER_ACTION_ID);
      if (action != null) {
        String iconPath = (autonumberState ? ImageResolver.AUTONUMBER_ENABLED_ICON : ImageResolver.AUTONUMBER_DISABLED_ICON);
        action.putValue(Action.SMALL_ICON, ImageResolver.getImage(iconPath));
      }
    }
  }
}
Can you help me figure out where I can initialize the action icon on editorOpen?
Radu
Posts: 9544
Joined: Fri Jul 09, 2004 5:18 pm

Re: How to create a menu action with an icon that toggles?

Post by Radu »

Hi,

Indeed, things would have been easier if we would allowed more control over implementing a toggle-like action directly from the framework configuration, we have an internal issue for this but we have not yet worked on that.
After an editor is opened, from what I remember the framework actions are loaded and the toolbar of the editor is reconfigured on a timer a bit later. So your current code might be executed too early.
I think that if you added an WSEditorListener to the opened editor and intercepted the callback "documentTypeExtensionsReconfigured" and on the callback try to make changes to the action that might work better...
How about two more possible approaches?

- Keep the Author action with a name something like "Configure automatic TOC handling ...", when the action is pressed, from the custom operation you show a custom Swing dialog in which the end user selects a radio choice and saves the setting persistently. In this way the Author action itself would no longer need to be a toggle as it would show a dialog.

- Implement the Action directly at plugin level, so from the plugin side add a customizer "ro.sync.exml.workspace.api.standalone.actions.MenusAndToolbarsContributorCustomizer" which can override different methods like "customizeAuthorPageExtensionMenu", "customizeAuthorPageExtensionToolbar", "customizeAuthorPopUpMenu" and allows you to create and add your own Swing action there.

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
gc_swilson39
Posts: 5
Joined: Wed Feb 19, 2025 7:35 pm

Re: How to create a menu action with an icon that toggles?

Post by gc_swilson39 »

Thanks for the multiple suggestions!
I'm sure I can get one of the approaches to work. I may actually go with the dialog approach, since it's usually better design to remove as many "moving parts" as possible.
Post Reply