Tuesday Jun 10, 2008

Statistics: They Can't Be Serious (Part 2)

I've mentioned the stupidity of surveys and statistics before, in Statistics: They Can't Be Serious. Today they Guardian has another one (again relating to tennis):

Go here to read it online or page 17 of the printed version.

What bugs me in particular is encapsulated in this sentence: "Swiss neuro-scientists found regular players were better at spotting subtle differences in speed, location and trajectory than others."

Isn't that the same as saying: "Regular swimmers can swim better than those who don't swim regularly?" Or: "People who read books regularly read better than those who don't?"

Or: "Stupid people who regularly put together silly statistics come up with dumber statistics than those who don't and aren't?"

Code for Rerun DropDownButtonFactory

I made some serious progress with my redeploy plugin today. Since it was inspired by Gareth Uren, who liked this functionality in Eclipse and misses it in NetBeans IDE, I decided I should try to make it as similar as possible to how it works in Eclipse. So, here it is, no longer in a separate window, but using the NetBeans org.openide.awt.DropDownButtonFactory class:

Let's step through the code required for this functionality. First, I have extended org.apache.tools.ant.module.spi.AntLogger, which is exposed in META-INF/services, in a file called "org.apache.tools.ant.module.spi.AntLogger":

public class StoreDeployedApps extends org.apache.tools.ant.module.spi.AntLogger {

    @Override
    public boolean interestedInSession(AntSession session) {
        return true;
    }

    @Override
    public boolean interestedInAllScripts(AntSession session) {
        return true;
    }

    @Override
    public String[] interestedInTargets(AntSession session) {
        return AntLogger.ALL_TARGETS;
    }

    @Override
    public void targetStarted(AntEvent event) {
        BufferedReader br = null;
        try {
            //Get the build-impl.xml:
            File buildImplXML = event.getScriptLocation();
            //From the build-impl.xml parent, get the project.xml:
            File projectXML = new File(buildImplXML.getParentFile(), "project.xml");

            String targetName = event.getTargetName();
            String projectName = null;
            String projectType = null;
            
            //Read the Dom and figure out the project name and type,
            //where the type is a string like "org.netbeans.modules.java.j2seproject":
            InputSource source = new InputSource(new FileInputStream(projectXML));
            org.w3c.dom.Document doc = XMLUtil.parse(source, false, false, null, null);
            org.w3c.dom.NodeList nodeList = doc.getElementsByTagName("\*");
            int length = nodeList.getLength();
            for (int i = 0; i < length; i++) {
                org.w3c.dom.Node currentNode = nodeList.item(i);
                String nodeName = currentNode.getNodeName();
                if ("name".equals(nodeName)){
                    projectName = currentNode.getTextContent();
                }
                if ("type".equals(nodeName)){
                    projectType = currentNode.getTextContent();
                }
            }
        
            //If the target name is run, send the build-impl.xml, the project name,
            //and the project type to our action class:
            if (targetName.equals("run")) {
                ListDeployedAppsAction.setProjectNames(buildImplXML, projectName, projectType);
            }
            
        } catch (SAXException ex) {
            Exceptions.printStackTrace(ex);
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        } finally {
            try {
                br.close();
            } catch (IOException ex) {
                Exceptions.printStackTrace(ex);
            }
        }
    }

    @Override
    public void targetFinished(AntEvent event) {
    }
    
}

And here's the action class, which is registered in the layer.xml file, just like any other action class that we want to be able to invoke from a toolbar button:

public class ListDeployedAppsAction extends CallableSystemAction {

    private static JButton dropDownButton;
    private static JPopupMenu popup;
    static JMenu menu;
    
    static void setProjectNames(File buildImplXML, String projectName, String projectType) {

        Image icon = null;

        if (projectType.equals("org.netbeans.modules.java.j2seproject")) {
            icon = Utilities.loadImage("/org/netbeans/modules/java/j2seproject/ui/resources/j2seProject.png");
        } else if (projectType.equals("org.netbeans.modules.web.project")) {
            icon = Utilities.loadImage("/org/netbeans/modules/web/project/ui/resources/webProjectIcon.gif");
        } else {
            icon = Utilities.loadImage("/org/netbeans/modules/project/ui/resources/runProject.png");
        }

        ImageIcon image = new ImageIcon(icon);

        menu = new JMenu();
        JMenuItem subItemRun;

        menu.setIcon(image);
        menu.setText(projectName);

        subItemRun = new JMenuItem("Run \\"" + projectName + "\\" again");
        subItemRun.addActionListener(new RunActionListener(buildImplXML));
        menu.add(subItemRun);

        popup.add(menu);

    }

    static class RunActionListener implements ActionListener {

        File file;

        public RunActionListener(File file) {
            this.file = file;
        }

        public void actionPerformed(ActionEvent e) {
            try {
                ActionUtils.runTarget(FileUtil.toFileObject(file), new String[]{"run"}, new Properties());
            } catch (IOException ex) {
                Exceptions.printStackTrace(ex);
            } catch (IllegalArgumentException ex) {
                Exceptions.printStackTrace(ex);
            }
        }
    }

    @Override
    public Component getToolbarPresenter() {

        Image iconImage = Utilities.loadImage("/org/netbeans/modules/project/ui/resources/runProject.png");
        ImageIcon icon = new ImageIcon(iconImage);

        popup = new JPopupMenu();

        dropDownButton = DropDownButtonFactory.createDropDownButton(
                new ImageIcon(
                new BufferedImage(32, 32, BufferedImage.TYPE_BYTE_GRAY)),
                popup);

        dropDownButton.setIcon(icon);

        return dropDownButton;

    }

    @Override
    public void performAction() {
    }

    @Override
    public String getName() {
        return "Deployed Apps";
    }

    @Override
    public HelpCtx getHelpCtx() {
        return null;
    }
    
}

That's it. Next I need to add a submenu item for removing menu items. Maybe also a configuration dialog for tweaking the launch configurations that are registered in the list. By the way, in the process of moving my code from a window to a dropdown button factory, I was able to improve my code in several ways. Refactoring rocks. It really lets you look at your old code afresh.

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
« June 2008 »
SunMonTueWedThuFriSat
1
6
13
19
26
28
29
     
       
Today