Armed with all those fine resources, I made my first DropDownButton. Then I wanted to do something practical and thought of all the times where I've known the NetBeans API classes I needed but not the layer entries for registering them. And that I'd then go through a wizard for no other reason than that I wanted the layer entries. And at some point you've got all your dependencies set, so the wizard isn't helpful for you then either. The one and only reason you're going through a wizard is to get the layer entries, also because of some strangeness like the fact that sometimes packages are separated by a hyphen and other times by a dot and you can never remember which is which.
So I created a new plugin that presents you with a DropDownButton with items representing a few of the key elements in the layer file. When you select one, some basic stubs are created in the layer file, as you can see below, the illustration showing the exact tags generated for the selected item:
Several enhancements are imaginable, such as having the items loaded from the user directory and letting the user register new items there via the Options window. Also the tags could be smarter and detect the class names and so on. But for now, and also because my focus wasn't this functionality but learning about the DropDownButton, it does the job fine.
Here's all the code, which will be extremely useful if you like DropDownButtons too:
package org.netbeans.modules.layerreg;
import java.awt.Component;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.image.BufferedImage;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.text.JTextComponent;
import org.netbeans.api.editor.EditorRegistry;
import org.openide.awt.DropDownButtonFactory;
import org.openide.util.HelpCtx;
import org.openide.util.Utilities;
import org.openide.util.actions.CallableSystemAction;
public class LayerRegistrationAction extends CallableSystemAction {
private static JButton dropDownButton;
private static ButtonGroup buttonGroup;
private static JPopupMenu popup;
private MyMenuItemListener menuItemListener;
@Override
public Component getToolbarPresenter() {
Image iconImage = Utilities.loadImage("org/netbeans/modules/layerreg/icon.png");
ImageIcon icon = new ImageIcon(iconImage);
popup = new JPopupMenu();
menuItemListener = new MyMenuItemListener();
buttonGroup = new ButtonGroup();
String[] names = {"Actions", "Loaders", "Menu", "TopComponent", "Toolbars"};
for (int i = 0; i < names.length; i++) {
String name = names[i];
JCheckBoxMenuItem item = new JCheckBoxMenuItem(name);
item.setName(name);
item.addActionListener(menuItemListener);
buttonGroup.add(item);
popup.add(item);
}
dropDownButton = DropDownButtonFactory.createDropDownButton(
new ImageIcon(
new BufferedImage(32, 32, BufferedImage.TYPE_BYTE_GRAY)),
popup);
dropDownButton.setIcon(icon);
dropDownButton.setToolTipText("Insert Layer Registration");
dropDownButton.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
int state = e.getStateChange();
if (state == ItemEvent.SELECTED) {
/\*\* show popup menu on dropdown button at position: (0, height) \*/
popup.show(dropDownButton, 0, dropDownButton.getHeight());
}
}
});
popup.addPopupMenuListener(new PopupMenuListener() {
public void popupMenuCanceled(PopupMenuEvent e) {
dropDownButton.setSelected(false);
}
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
dropDownButton.setSelected(false);
}
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
}
});
return dropDownButton;
}
private class MyMenuItemListener implements ActionListener {
public void actionPerformed(ActionEvent ev) {
JMenuItem item = (JMenuItem) ev.getSource();
String desiredInsertion = item.getName();
JTextComponent editor = EditorRegistry.lastFocusedComponent();
if (desiredInsertion.equals("Actions")) {
editor.replaceSelection(ACTIONS);
} else if (desiredInsertion.equals("Loaders")) {
editor.replaceSelection(LOADERS);
} else if (desiredInsertion.equals("Menu")) {
editor.replaceSelection(MENU);
} else if (desiredInsertion.equals("Toolbars")) {
editor.replaceSelection(TOOLBARS);
} else if (desiredInsertion.equals("TopComponent")) {
editor.replaceSelection(TOPCOMPONENT);
}
}
}
String ACTIONS =
"<folder name=\\"Actions\\">\\n" +
" <folder name=\\"MyCategory\\">\\n" +
" <file name=\\"org-bla-bla-bla-MyOneAction.instance\\"/>\\n" +
" <file name=\\"org-bla-bla-bla-MyTwoAction.instance\\"/>\\n" +
" </folder>\\n" +
" <folder name=\\"MyOtherCategory\\">\\n" +
" <file name=\\"org-bla-bla-bla-MyOtherAction.instance\\"/>\\n" +
" </folder>\\n" +
"</folder>\\n";
String MENU =
"<folder name=\\"Menu\\">\\n" +
" <folder name=\\"MyMenu\\">\\n" +
" <file name=\\"MyAction.shadow\\">\\n" +
" <attr name=\\"originalFile\\" stringvalue=\\"Actions/MyCategory/org-bla-bla-bla-MyAction.instance\\"/>\\n" +
" </file>\\n" +
" </folder>\\n" +
"</folder>\\n";
String TOOLBARS =
"<folder name=\\"Toolbars\\">\\n" +
" <folder name=\\"MyToolbar\\">\\n" +
" <attr name=\\"SystemFileSystem.localizingBundle\\" stringvalue=\\"org.bla.bla.Bundle\\"/>\\n" +
" <file name=\\"org-bla-bla-bla-MyAction.instance\\">\\n" +
" <attr name=\\"SystemFileSystem.localizingBundle\\" stringvalue=\\"org.bla.bla.Bundle\\"/>\\n" +
" <attr name=\\"position\\" intvalue=\\"400\\"/>\\n" +
" </file>\\n" +
" </folder>\\n" +
"</folder>\\n";
String LOADERS =
"<folder name=\\"Loaders\\">\\n" +
" <folder name=\\"text\\">\\n" +
" <folder name=\\"x-mime\\">\\n" +
" <folder name=\\"Actions\\">\\n" +
" <file name=\\"org-openide-actions-CopyAction.instance\\">\\n" +
" <attr name=\\"position\\" intvalue=\\"500\\"/>\\n" +
" </file>\\n" +
" </folder>\\n" +
" </folder>\\n" +
" </folder>\\n" +
"</folder>\\n";
String TOPCOMPONENT =
"<folder name=\\"Windows2\\">\\n" +
" <folder name=\\"Components\\">\\n" +
" <file name=\\"MyTopComponent.settings\\" url=\\"MyTopComponentSettings.xml\\"/>\\n" +
" </folder>\\n" +
" <folder name=\\"Modes\\">\\n" +
" <folder name=\\"MyMode:-editor-or-explorer-or-properties-etc\\">\\n" +
" <file name=\\"MyTopComponent.wstcref\\" url=\\"MyTopComponentWstcref.xml\\"/>\\n" +
" </folder>\\n" +
" </folder>\\n" +
"</folder>\\n";
//Unused:
@Override
public void performAction() {
}
//Unused:
public String getName() {
return "";
}
public HelpCtx getHelpCtx() {
return HelpCtx.DEFAULT_HELP;
}
@Override
protected boolean asynchronous() {
return false;
}
}
I've played around with the DropDownButtonFactory for few weeks right now and I found something embarrassing.
I use a DropDownButton with an arrow to navigate Back and Forth in a browser. Unfortunatly, there is no possibility on a JButton (returned by DropDownButtonFactory) to know if the use clicked on the button itself or on the small arrow.
My solution: Copy the code of org.openide.awt.DropDownButton and set method isInArrowArea() public
Then it is easy in the mouseClicked listener to know what part of the button was clicked exactly
Thanks Emmanuel, very interesting. I passed this info on to the responsible engineer.
1155<a href='http://butbaker.ks-muryoukoukoku.com/' target='_blank'>butbakerアクセスアップステーション</a><br>
1156<a href='http://www.k-sogolinknow.com/' target='_blank'>検索サイト上位、総合リンクnow</a><br>
1157<a href='http://sheep.k-sogolinknow.com/' target='_blank'>sheep総合リンクnow</a><br>
Nice tutorial...
I have one question, whats the use of having ButtonGroup? After adding items into it, the code is not using it anywhere..
Also, like Antonio asked today on mailing lists..Can we make it Context Aware?
Thanks!
Hello.
I'd really apreciate your tutorial.
But, I couldn't find the lib org.openide.
Where can I find it?
Please, forgive my english...
It's part of the NetBeans Platform. Download NetBeans IDE and you will have it for free.
I'm trying to make an import to that package, but the netbeans can't find it.
is that correct?
When one adds text to the button, the arrow curiously appears in the centre of the button. I would like this order of appearance: Icon, text, arrow. I could live with: Icon, arrow, text, but then at least clicking on the arrow should show the popup, instead one still has to click near the right edge of the button.
Any ideas?