Page 1 of 1

Add new menu in CSSAlternativesToolbar

Posted: Wed Jun 18, 2025 7:44 pm
by Isabelle
Hello,

We use oxygen sdk 27.1.0.1.
We want to add two JCheckBoxMenuItem into the JToolBar provided from createCSSAlternativesToolbar.
We use this code :

Code: Select all

public class CSSAlternativesToolBar extends ToolBar {

    private JCheckBoxMenuItem showTabNbspEolEof;

    private JCheckBoxMenuItem showTabNbspEolEofSpace;

    public CSSAlternativesToolBar(String key, String title, DefaultDockableBarDockableHolder defaultDockableBarDockableHolder) {
        super(key, title, defaultDockableBarDockableHolder);        
        showTabNbspEolEof = new JCheckBoxMenuItem("+ Show TAB/NBSP/EOL/EOF", true);
        showTabNbspEolEofSpace = new JCheckBoxMenuItem("+ Show TAB/NBSP/EOL/EOF & Space", false);
    }

    private void addCSSAlternativesToolbar(OxygenComponent oxygenComponent) {
        JToolBar cssAlternativesToolBar = ((WSAuthorComponentEditorPage) oxygenComponent.getAuthorComponentProvider().getWSEditorAccess().getCurrentPage()).createCSSAlternativesToolbar();

        JMenu cssMBP = (JMenu) cssAlternativesToolBar.getComponent(0);
        cssMBP.setFont((Font) UIManager.getLookAndFeelDefaults().get("defaultFont"));

        JPopupMenu popupMenu = cssMBP.getPopupMenu();
        popupMenu.add(showTabNbspEolEof);
        popupMenu.add(showTabNbspEolEofSpace);

        add(cssMBP);
    }
}
in the exf file we have this :

Code: Select all

<css selectMultipleAlternateCSS="true" mergeDocument="false">
   <addCss path="${frameworks}/default/proced.author-desktop.css" alternate="false"/>
   <addCss path="${frameworks}/default/comment-hide.css" title="Default" alternate="false"/>
   <addCss path="${frameworks}/default/comment-show.css" title="+ Show comments" alternate="true"/>
   <addCss path="${frameworks}/default/non-breaking-space.css" title="+ Show non-breaking space" alternate="true"/>
</css>
The 2 new options are displayed in the Styles menu, and worked well.
But when we use other menu options like + Show non-breaking space then we have this issue :
java.lang.NullPointerException: Cannot read field "zxg" because "<local4>" is null
at ro.sync.exml.editor.xmleditor.pageauthor.w.xgn(Unknown Source)
at ro.sync.exml.editor.xmleditor.pageauthor.w.rgn(Unknown Source)
at ro.sync.exml.editor.xmleditor.pageauthor.w$1.run(Unknown Source)
at ro.sync.ui.we$_b.run(Unknown Source)
at ro.sync.ui.we.x(Unknown Source)
at ro.sync.ui.we.l(Unknown Source)
at ro.sync.exml.editor.xmleditor.pageauthor.w.dhn(Unknown Source)
at ro.sync.exml.editor.xmleditor.pageauthor.w$_b.actionPerformed(Unknown Source)
at java.desktop/javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at java.desktop/javax.swing.JToggleButton$ToggleButtonModel.setPressed(Unknown Source)
at java.desktop/javax.swing.AbstractButton.doClick(Unknown Source)
at java.desktop/javax.swing.plaf.basic.BasicMenuItemUI.doClick(Unknown Source)
at java.desktop/javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(Unknown Source)
at java.desktop/java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
at java.desktop/java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
at java.desktop/java.awt.Component.processMouseEvent(Unknown Source)
at java.desktop/javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.desktop/java.awt.Component.processEvent(Unknown Source)
at java.desktop/java.awt.Container.processEvent(Unknown Source)
at java.desktop/java.awt.Component.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.Component.dispatchEvent(Unknown Source)
at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.Window.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.Component.dispatchEvent(Unknown Source)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.desktop/java.awt.EventQueue$5.run(Unknown Source)
at java.desktop/java.awt.EventQueue$5.run(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.desktop/java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.run(Unknown Source)
at ro.sync.ui.we.g(Unknown Source)
at ro.sync.ui.we.x(Unknown Source)
at ro.sync.ui.we.l(Unknown Source)
at ro.sync.exml.editor.xmleditor.pageauthor.w.dhn(Unknown Source)
at ro.sync.exml.editor.xmleditor.pageauthor.w$_b.actionPerformed(Unknown Source)
at java.desktop/javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at java.desktop/javax.swing.JToggleButton$ToggleButtonModel.setPressed(Unknown Source)
at java.desktop/javax.swing.AbstractButton.doClick(Unknown Source)
at java.desktop/javax.swing.plaf.basic.BasicMenuItemUI.doClick(Unknown Source)
at java.desktop/javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(Unknown Source)
at java.desktop/java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
at java.desktop/java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
at java.desktop/java.awt.Component.processMouseEvent(Unknown Source)
at java.desktop/javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.desktop/java.awt.Component.processEvent(Unknown Source)
at java.desktop/java.awt.Container.processEvent(Unknown Source)
at java.desktop/java.awt.Component.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.Component.dispatchEvent(Unknown Source)
at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.Window.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.Component.dispatchEvent(Unknown Source)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.desktop/java.awt.EventQueue$5.run(Unknown Source)
at java.desktop/java.awt.EventQueue$5.run(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.desktop/java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.run(Unknown Source)
Do you know why we get this issue ?
How can we add properly new options to CSSAlternativesToolbar ?

Thanks,
Regards,
Isabelle

Re: Add new menu in CSSAlternativesToolbar

Posted: Thu Jun 19, 2025 6:35 am
by Radu
Hi Isabella,
The CSS drop down button itself is not public API, inside it has its own custom code which at times iterates the components and considers that for example all menu items inside it contain actions of a certain Oxygen specific class. It encounters one of your JCheckBoxMenuItem's and attempts to retrieve an action from it and casts it to an internal class, this makes the class cast occur. I can try to make the code more robust for a future version but it will still not be public API, maybe you can create your own separate drop down styles panel for the additional styles for which you want to dynamically add actions..
You can use the "ro.sync.exml.workspace.api.standalone.ui.OxygenUIComponentsFactory.createSplitMenuButton(String, Icon, boolean, boolean, boolean, boolean)" API to create a drop down menu-like button.
Regards,
Radu

Re: Add new menu in CSSAlternativesToolbar

Posted: Tue Jul 01, 2025 10:14 am
by Isabelle
Hello Radu,

Thanks for your feedback.
I have created my own JMenu.

Regards,
Isabelle