Key Promoter for NetBeans

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

Comments:

Make it so :-) that looks very handy.

Posted by Kyle Rose on August 18, 2014 at 09:21 AM PDT #

Great to hear -- here it is: http://plugins.netbeans.org/plugin/55751/?show=true

Posted by Geertjan on August 19, 2014 at 04:37 AM PDT #

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

Posted by Claudio Rosati on August 21, 2014 at 02:41 AM PDT #

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

Posted by guest on August 21, 2014 at 02:49 AM PDT #

Claudio, good idea, thanks, will implement this.

Posted by Geertjan on August 23, 2014 at 09:27 PM PDT #

Very nice plugin. Well done.

Posted by guest on December 14, 2014 at 03:04 PM PST #

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

Posted by guest on December 15, 2014 at 02:10 AM PST #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.

Search

Archives
« March 2015
SunMonTueWedThuFriSat
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
    
       
Today