X

Geertjan's Blog

  • August 18, 2014

Key Promoter for NetBeans

Geertjan Wielenga
Product Manager

Whenever a menu item or toolbar button is clicked, it would be handy if NetBeans were to tell you 'hey, did you know, you can actually do this via the following keyboard shortcut', if a keyboard shortcut exists for the invoked action.

After all, ultimately, a lot of developers would like to do everything with the keyboard and a key promoter feature of this kind is a helpful tool in learning the keyboard shortcuts related to the menu items and toolbar buttons you're clicking with your mouse.

Above, you see the balloon message that appears for each menu item and toolbar button that you click and, below, you can see a list of all the actions that have been logged in the Notifications window. That happens automatically when an action is invoked (assuming the plugin described in this blog entry is installed), showing the display name of the action, together with the keyboard shortcut, which is presented as a hyperlink which, when clicked, re-invokes the action (which might not always be relevant, especially for context-sensitive actions, though for others it is quite useful, e.g., reopen the New Project wizard).


And here's all the code. Notice that I'm hooking into the 'uigestures' functionality, which was suggested by Tim Boudreau, and I have added my own handler, which was suggested by Jaroslav Tulach, which gets a specific parameter from each new log entry handled by the 'org.netbeans.ui.actions' logger, makes sure that the parameter actually is an action, and then gets the relevant info from the action, if the relevant info exists:

@OnShowing
public class Startable implements Runnable {
    @Override
    public void run() {
        Logger logger = Logger.getLogger("org.netbeans.ui.actions");
        logger.addHandler(new StreamHandler() {
            @Override
            public void publish(LogRecord record) {
                Object[] parameters = record.getParameters();
                if (parameters[2] instanceof Action) {
                    Action a = (Action) parameters[2];
                    JMenuItem menu = new JMenuItem();
                    Mnemonics.setLocalizedText(
                            menu,
                            a.getValue(Action.NAME).toString());
                    String name = menu.getText();
                    if (a.getValue(Action.ACCELERATOR_KEY) != null) {
                        String accelerator = a.getValue(Action.ACCELERATOR_KEY).toString();
                        NotificationDisplayer.getDefault().notify(
                                name,
                                new ImageIcon("/org/nb/kp/car.png"),
                                accelerator,
                                new ActionListener() {
                            @Override
                            public void actionPerformed(ActionEvent e) {
                                a.actionPerformed(e);
                            }
                        });
                    }
                }
            }
        });
    }
}

Indeed, inspired by the Key Promoter in IntelliJ IDEA.

Interested in trying it out? If there's interest in it, I'll put it in the NetBeans Plugin Portal.

Update 08/19/14: OK, here it is -- http://plugins.netbeans.org/plugin/55751

Join the discussion

Comments ( 7 )
  • Kyle Rose Monday, August 18, 2014

    Make it so :-) that looks very handy.


  • Geertjan Tuesday, August 19, 2014
  • Claudio Rosati Thursday, August 21, 2014

    Very nice, but... soon the Notifications windows will be full of messages.

    I think that actions triggered by keyboard shortcuts should never be recorded/notified.

    This is an entry for a keyboard generated action (Undo - CTRL+Z):

    <param>java.awt.event.ActionEvent[ACTION_PERFORMED,cmd=Ctrl+Z,when=1408613043528,modifiers=Ctrl] on org.openide.text.QuietEditorPane[,0,-5104,1001x7259,layout=javax.swing.plaf.basic.BasicTextUI$UpdateHandler,alignmentX=0.0,alignmentY=0.0,border=,flags=33554728,maximumSize=,minimumSize=,preferredSize=,caretColor=java.awt.Color[r=255,g=255,b=0],disabledTextColor=,editable=true,margin=java.awt.Insets[top=0,left=0,bottom=0,right=0],selectedTextColor=,selectionColor=,kit=org.netbeans.modules.editor.java.JavaKit@2238f3af,typeHandlers=]</param>

    and the following is from a menu item selection (Copy):

    <param>java.awt.event.ActionEvent[ACTION_PERFORMED,cmd=Ctrl+C,when=1408613387339,modifiers=Button1] on javax.swing.JMenuItem[,1,25,181x19,invalid,alignmentX=0.0,alignmentY=0.0,border=javax.swing.plaf.synth.SynthBorder@3468af39,flags=384,maximumSize=,minimumSize=,preferredSize=,defaultIcon=,disabledIcon=,disabledSelectedIcon=,margin=javax.swing.plaf.InsetsUIResource[top=0,left=0,bottom=0,right=0],paintBorder=false,paintFocus=false,pressedIcon=,rolloverEnabled=false,rolloverIcon=,rolloverSelectedIcon=,selectedIcon=,text=Copy]</param>

    Probably a check on the "modifiers" value (Ctrl vs Button1) could be discriminate which action be notified and which not.

    Claudio


  • guest Thursday, August 21, 2014

    Very nice, but... soon the Notifications windows will be full of messages.

    I think that actions triggered by keyboard shortcuts should never be recorded/notified.

    This is an entry for a keyboard generated action (Undo - CTRL+Z):

    <param>java.awt.event.ActionEvent[

    ACTION_PERFORMED,

    cmd=Ctrl+Z,

    when=1408613043528,

    modifiers=Ctrl

    ] on org.openide.text.QuietEditorPane[...]</param>

    and the following is from a menu item selection (Copy):

    <param>java.awt.event.ActionEvent[

    ACTION_PERFORMED,

    cmd=Ctrl+C,

    when=1408613387339,

    modifiers=Button1

    ] on javax.swing.JMenuItem[...]</param>

    Probably a check on the "modifiers" value (Ctrl vs Button1) could be discriminate which action be notified and which not.

    Claudio


  • Geertjan Sunday, August 24, 2014

    Claudio, good idea, thanks, will implement this.


  • guest Sunday, December 14, 2014

    Very nice plugin. Well done.


  • guest Monday, December 15, 2014

    @Geertjan would it be possible to make it compatibile with version 1.7 of Java?


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.