Friday Jul 26, 2013

NetBeans IDE for Groovy Purists

The Groovy support in NetBeans IDE is based on two use cases. In the first case, you're a Java programmer and want to use Groovy as a support language; therefore, in this scenario, you'll create a Java project and then add Groovy artifacts (Groovy classes and scripts) and go from there. In the second case, you're using Grails, in which case you'll go to the Groovy category in the New Project wizard (Ctrl-Shift-N) and create a Grails project and continue developing from that point onwards.

But what about if you don't care about Java and you don't care about Grails? You simply want to write Groovy scripts, compile them, debug them, and run them.

Download this plugin and install it into NetBeans IDE 7.3.1, which is the latest stable release of NetBeans IDE, though it may work in later versions of NetBeans IDE too:

http://plugins.netbeans.org/plugin/49928/?show=true

Either install the plugin into the All distribution of NetBeans IDE 7.3.1 or first install the "Groovy & Grails" plugin (via Tools | Plugins) into any other download bundles of NetBeans IDE.

Now you have this new project available in the New Project wizard:

(Sorry for typo "Wheen" in above, will fix in next release...)

Complete the wizard and you should see this:

In other words, you have no Java source files at all, just a Groovy script, and the Groovy JAR (which you can change in the Project Properties dialog) and the JDK (which can also be changed in the Project Properties dialog).

Open the file and you see a Groovy editor:

Right-click in the left margin (or click on a line number) and you can set a breakpoint, visualized by a red line. Then start the Debugger (there's a Debug menu in the main menubar, take a look there).

Hope that helps Groovy purists get started with NetBeans IDE! Feedback welcome, e.g., let me know what other content you'd like the Groovy project to have.

Now go here to read about the latest Groovy features in NetBeans IDE:

https://blogs.oracle.com/netbeansgroovy/

In other news. I'm on vacation until Monday 5 August, if you don't hear from me before then, now you know why!

Thursday Jul 25, 2013

"Just How Messed Up Is My Code?"

More often than not, you know your code is pretty messed up. The excuse you have is that you inherited it from someone else. That, of course, doesn't change the fact that your code is messed up. It changes how responsible you feel about it but, as you'll soon be reminded by someone, the fact that you now own the code means that it's your responsibility now. The fact that your code works doesn't mean that you understand it and that's because the code is messed up in numerous different and interesting ways. The fact that you don't understand how it works means that it's hard to maintain it.

So, wouldn't it be handy to know how many messy methods you have, and where they are found in your application, that is, where exactly are the worst culprits, those that are just really wildly long with multiple nested clauses and loops and return statements everywhere? And what about all those classes with bizarre numbers of constructors? Or the constructors where dozens of parameters are received or classes that are hopelessly intertwined with other classes? Then at least you'll know where the main problems are found.

Enter NetBeans code metrics, introduced in NetBeans IDE 7.4 which, at the time of writing, is in its Beta phase. Go to Source | Inspect in the main menubar of NetBeans IDE. Choose a "Scope", i.e., do you want to search for messed up code in the current file, package, project, or all open projects? Then, in the Configuration drop-down, skip over the predefined configurations and choose "Default" at the end. Now the "Manage" button becomes enabled; click it. In the Configurations drop-down, select New, and name the configuration, "Java Code Metrics", under Analyzer choose "NetBeans Java Hints", and then check "Java Code Metrics". Take a look at the long list of inspections available for code metrics, all introduced in NetBeans IDE 7.4. Each of them can be configured, i.e., you can decide what "too much" and "too many" means:

Click OK. Now you'll have a new "Java Code Metrics" configuration. Click Inspect. Now, within the specified scope, all the messed up code is identified:

Click on an item in the view above to jump to the offending code. Then, fix it! Yes, fixing messed up code is a manual process. Hey, NetBeans IDE can't do everything for you...

Note: I initially tried the above in NetBeans IDE 7.4 Beta, and it didn't return results, though when I tried it in the latest development build, the results above were shown. So it appears that problems with this functionality have been fixed since the Beta was released, therefore download the latest development build if you want to play with this functionality. Your feedback and experiences with this would be great to hear about.

Wednesday Jul 24, 2013

From Auction to Awesome with NetBeans IDE

In NetBeans IDE 7.4, which is currently in its Beta release, go to the New Project wizard and search for 'websocket'. You'll find three very cool WebSocket samples are now bundled with the IDE. Let's play with the "Auction WebSocket (Java EE 7)" sample. Select it and complete the wizard.

Note that the application you now have is a Java EE application on Maven, with HTML, JavaScript, and CSS on the frontend, and Java (using WebSocket as the basis of an auction scenario) on the backend:

Select "Chrome with NetBeans Integration" in the handy new browser switcher in the toolbar. Run the application and the initial page opens in the Chrome browser. In 7.4, for the first time, you'll now see the NetBeans icon in the top right of the browser for your Maven-based Java web project, if you have installed the NetBeans plugin into Chrome. Below the mouse is over "Enter your user name" in the browser.

Prior to NetBeans IDE 7.4, the NetBeans icon in the Chrome browser (provided via a NetBeans plugin for Chrome), which gives you access from the browser to the IDE, was only available for pure HTML projects, i.e., there's a special type of project introduced in NetBeans IDE 7.3, for working with HTML, JavaScript, and CSS files. However, now that special support introduced in 7.3 is also available to Java web projects and PHP projects.

Therefore, you can now select, as has been done in the screenshot above, "Inspect in NetBeans" mode, which lets you click items in the browser, causing the corresponding nodes in the Navigator in the IDE to be highlighted. From a node in the Navigator, you can right-click to jump to the source in the editor. 

In the editor, change something, save, and the browser is automatically refreshed to display your change. 

Conversely, you can browse and identify items in the browser by hovering over the nodes in the Navigator in the IDE. Below, the mouse is over the second to last node in the Navigator.

Next, you can set breakpoints in a JavaScript file in the project. After you've set a breakpoint, simply refresh the browser to start the debug session. In other words, the process of running the application again in debug mode is not needed. Instead, refreshing the browser is all that's needed to pick up the breakpoints set in a file. 

Best of all, you can debug the frontend and backend at the same time, i.e., debug Java and JavaScript simultaneously. Run the application in debug mode. In the Sessions window, you'll see two debug sessions have started up. You can quickly switch between the sessions as needed.

Also, the brand new Network Monitor is available. WebSocket communication is automatically displayed in it:

Awesome, right? 

For further and related information, see the NetBeans WebClient blog's article HTML5 Development for Java EE and PHP projects.

Tuesday Jul 23, 2013

NetBeans @ JavaOne China 2013

In Shanghai, a great moment at the start of JavaOne China 2013 for me, from a NetBeans perspective, was meeting the NetBeans booth staff, all great Oracle folks from Oracle Shanghai:

Above, you see, among others, Fred, Geertjan (me), Patrick, Sheldon, Felix, Kevin, Lily, JiBing, and Tristan ! (Also note that I appear to have found the Chinese implementation of Zoran Sevarac from Belgrade, Serbia.)

I gave the group an overview of cool things to show and do in NetBeans IDE. In particular, the ability to click in the Chrome browser and see where artifacts are defined in the IDE has been a big focus in the demos we've done at the booth.

Very quickly everyone got involved in introducing JavaOne attendees to the cool features in NetBeans IDE. Really nice to see how enthusiastic the booth staff is and how helpful and assertive in drawing passersby into demo scenarios.

And, today, the NetBeans hands on lab "Unlocking Java EE with HTML5" (PDF downloadable here) was completely packed out. Many thanks to Fred, Sheldon, and Patrick, who were fantastic proctors, very helpful and patient in helping with questions that arose.

Finally, tomorrow, a session will be held entitled "What's New in NetBeans IDE", where the great features in 7.3, 7.3.1, and 7.4 will be highlighted and demonstrated.

Aside from the weather, which is definitely not, everything is very cool here!

Monday Jul 22, 2013

Official Support for PhoneGap in NetBeans IDE

PhoneGap is a free and open source framework that allows you to create cross-platform mobile applications with standards-based Web technologies, such as HTML, JavaScript, and CSS.

NetBeans IDE 7.4, with its Beta released a few days ago, supports PhoneGap. For free. Without the need to install plugins. Because the NetBeans IDE free PhoneGap support is provided out of the box when you install the Java EE or All distributions of NetBeans IDE 7.4.

Here's a sample PhoneGap app deployed in my Android emulator:

The IDE lets you register artifacts for Android and iOs:

A complete sample is available to get you started, showing you how to write rich mobile applications in HTML5 and Javascript using JQuery, PhoneGap with the Geolocation API and Contacts API, together with the Google Maps API. Since this is developed via PhoneGap, the very same code can be tried out and deployed on both iOS and Android devices.

A blank project skeleton can also be created:

A PhoneGap application is just a flavor of an HTML5 application, so you can turn any HTML5 application into a PhoneGap application very easily:

Deployment to various devices can be set globally via the new browser switcher in the toolbar or per-project in the Project Properties dialog as shown below:

Reference: http://wiki.netbeans.org/NewAndNoteworthyNB74#PhoneGap

Saturday Jul 20, 2013

From Namaste to Nihao with NetBeans

The last few days I spent in Mumbai, India, at an Oracle office doing Oracle things. Beyond that, I can't say much, hopefully more sometime in the coming months! It was very interesting and intense and I'm looking forward to sharing more about that when the time is right. No time for sightseeing, well, except for the elevator up to the n-th floor of the building, which enabled this view:

Then on via Delhi to Shanghai, China, where the weather is quite different, as this picture shows (though in both places everyone was out in the street with umbrellas, though for opposite reasons, i.e., it was 37'C in Shanghai today), also from high up in a building where I'm spending my days until JavaOne China begins next week:

Interesting times for me, for sure! Really looking forward to meeting up with JavaOne China attendees next week. When I'm not presenting sessions about NetBeans, you'll find me at the NetBeans booth!

Friday Jul 19, 2013

Skeleton WireFrame Designer (Part 2)

The basic wireframe designer is really taking off now. One can add and delete tables, rows, and items to/from the designer window, all from the explorer window. And the two windows are in separate modules.

When more rows are added to the table than the visible space allows, the table enlarges and the other tables move down. When the user right-clicks a widget, the same actions as on the nodes in the explorer window are displayed, e.g., for adding/removing new widgets appropriate to the current context.

One cool thing will be to add support for inserting widgets between other existing widgets, e.g., a new table between two existing tables. And finally, this will be backed by an XML file, which will let the user generate various outputs from the design.

Thursday Jul 18, 2013

Skeleton WireFrame Designer (Part 1)

Let's say you need to manage a centralized GUI-type designer from a node hierarchy. To really picture this concept, take a look at this screenshot, where on the left you see a node hierarchy and on the right a designer. When the user right-clicks the root node, new table-elements (whatever that may be in the context of your implementation of this scenario) are added to the designer. Existing tables can also be deleted, via the node hierarchy.


If you're creating some kind of wireframe-oriented application, i.e, you want to let the user quickly put together a layout of some kind, without drag-and-drop,  but by continually expanding some kind of tree structure, i.e., node hierarchy, then this scenario is specifically made with you in mind.

And here's the structure of the application. It is extremely simple and elegant, the starting point is a domain module, providing a Table object and a Row object. When the user right-clicks the root node, a new Table can be created, which means that a Table object is added to the CentralLookup, i.e., a context-free implementation of the Lookup concept, with thanks to Wade and others. Similarly, a Row can be added by right-clicking the Table node, which is the entry point to adding a new Row to the CentralLookup. On the other end, i.e., in a different module, a LookupListener on the designer TopComponent detects additions/removals and behaves appropriately, i.e., adds/removes corresponding Visual Library widgets to/from a Visual Library Scene:

I will be developing this scenario further in the coming days. Interested? Here's where the source code is found:

https://java.net/projects/nb-api-samples/sources/api-samples/show/versions/7.3/misc/WireFrameBasis

Wednesday Jul 17, 2013

Dependency Search Hint for Ant-Based NetBeans Platform Applications

In addition to the handy new Export Package menu item mentioned yesterday, from NetBeans Platform 7.4 onwards you can now directly access the Module Dependency dialog, via a hint in the Java Editor

That's always been available for Maven-based NetBeans Platform application, but thanks to Benno Markiewicz this is now also available for plain old Ant projects:

http://wiki.netbeans.org/NewAndNoteworthyNB74#Hints_2

https://netbeans.org/bugzilla/show_bug.cgi?id=212656

I believe that enhancements such as this one, rather than large features, i.e., small and helpful new hints and refactorings, is what makes the difference between a good and great IDE. Hope Benno and others will continue this great trend!

Tuesday Jul 16, 2013

Export Package Action for NetBeans Platform Applications

In the real world, i.e., the unhypy world of plain old grunt work Java coding, we find ourselves far removed from 'trends' and 'recent developments'. Handy to have new and improved tools to help us out and also to know that those tools keep on getting better. 

In the past, you'd expose a package to the rest of the modular NetBeans Platform application via a slightly cumbersome process of clicks in different places. No more. Instead, there's now an Export menu item on package nodes in NetBeans module projects:

Invoke the Action, i.e., click the menu item, and the project.xml file is updated, as visualized by the package icon, which immediately has an unlocked symbol attached to it.

Available from NetBeans Platform 7.4 onwards, as outlined in the New & Noteworthy:

http://wiki.netbeans.org/NewAndNoteworthyNB74#Export_Package_on_packages_in_NetBeans_modules

Monday Jul 15, 2013

NetBeans IDE 7.4 Beta: Rich Browser Integration for Java EE and PHP

Whenever I demonstrated the brilliant NetBeans tools for synchronizing HTML, JavaScript, and CSS files with the browser, guess what the very first question was that I got each and every time? Here it is:

Yeah, very interesting, guy. But we're not coding HTML pages by hand anymore. Instead, our HTML files are generated from PHP or JSP or JSF. So, drop us a line when you've got bidirectional synchronization with the browser working for those kinds of files, OK?

Point taken and NetBeans IDE 7.4 Beta, released today, has catered to exactly the scenario described above. From the New & Noteworthy:

"You can now use all the HTML5 development features (collectively known as Project Easel) in Java Web applications (Ant or Maven based) and in PHP applications. For a more detailed description, see the Java EE and PHP sections of this document."

Hurray and I'll be sharing some great YouTube movies about the above scenarios soon!

An excellent article and authoritative on this topic:

https://blogs.oracle.com/netbeanswebclient/entry/html5_development_with_java_ee

Saturday Jul 13, 2013

Prototype of JavaFX Performance Analyzer on New Framework

Johannes Weigend, who will be at JavaOne again this year, has been prototyping a JavaFX version of his Software EKG application, which is an application performance analyzer created on the NetBeans Platform. Here's the original NetBeans Platform based application:

The prototype JavaFX version of the application (shown below) is developed on a lightweight OSGi-based rich-client application framework inspired by the NetBeans Platform. Currently it has a startup module, a window system, and a module system. Though there are the beginnings of other open source JavaFX frameworks which do something similar, Johannes couldn't identify one that fit his needs, which makes sense considering that application frameworks for JavaFX are all pretty new anyway, and so he led the development of a new one, as a bachelor thesis at the University of Applied Sciences Rosenheim where he teaches. Plans are to open source the framework in August of this year.

Seeing work being done, like the above, on application frameworks for JavaFX, is really promising. Given the various application frameworks available in the Swing world, it's still pretty hard to choose JavaFX over Swing when you're creating pure data-oriented software where the enhanced appearance provided by JavaFX is not a functional requirement. Productivity gains on the coding level, in the sense that JavaFX does well in solving the cumbersomeness of Swing coding, are never going to be significant enough to outweigh the productivity gains of fully fledged application frameworks, with all their prebuilt pluggable components, years of developer hours, and design patterns, in the same way as the fact that matchsticks are now better than before is not going to make me switch from lego to matchsticks when I want to build a toy house really fast and reliably. But, the combination of knowing (or hoping or believing or betting) that "JavaFX is the future" (always bear in mind that nothing is the future until the future is the present that creates a different future) with the availability of fullblown application frameworks, makes JavaFX a serious alternative to Swing, in the context of large data-oriented software systems, as opposed to games and animation-oriented applications where JavaFX is the obvious choice already.

Still, it's hard to bask in the shade of a sapling when you know there's a sturdy oak tree nearby.

Friday Jul 12, 2013

BMW Body Shop Quality Management on the NetBeans Platform

"Graphical Based Quality Planning And Control" is a tool for quality management in body shops at BMW Group. The software is used for body shop quality management in every plant of the BMW Group all over the world.

The tool provides functions for modeling the following:

  • facilities (trees of production equipment)
  • assemblies (trees of parts and work items)
  • drawings (images plus dynamic content)
  • stations (inspection, rework)

For each station, users define various checks, which have to be performed in the production areas. The inspectors have to check all work items made by robots and humans based on the drawings containing various dynamic items, such as welding points, weld seams, bond seams, and screws. These items are presented as dots, lines, polygons, grids and text content.

The software is built on top of NetBeans Platform 7.2 using a lot of functionality provided by the platform, such as trees, windows, visual library, and the auto update mechanism.

Body shop drawing:

Floor panel drawing tree:

Floor panel property sheet:

Hood drawing:

Side frame drawing:

Thursday Jul 11, 2013

Yet Another NetBeans Platform Application: Oracle JDeveloper 12c

There's a lot to recognize in the recently released Oracle JDeveloper 12c. Definitely time to add it to the NetBeans Platform Showcase, since JDev 12c is now visibly a NetBeans Platform application, along with hundreds of other applications, such as Microchip MPLAB X, Lua Glider, DbWrench, VisualVM, and jMonkeyEngine SDK, to name just a few of at least hundreds (that we know of, though I suspect thousands) of others.

In the release notes, notice paragraphs such as this: "The JDeveloper and NetBeans teams are working together to bring the best of each of its Java UI visual editing tools to all users. This release introduces the "Matisse" editor from NetBeans in JDeveloper."

There's been a bit of activity on Twitter about these developments, which are described in historical detail at Jaroslav Tulach's blog, specifically here: http://wiki.apidesign.org/wiki/JDeveloper

Tuesday Jul 09, 2013

Code Completion for Ceylon NetBeans Plugin

Ceylon code completion is simple to introduce via the NetBeans Code Completion Tutorial:

The only problem is that I don't know the Ceylon API to use to obtain all the keywords. Right now they're hardcoded after I copied/pasted them into my source code directly from here:

http://ceylon-lang.org/documentation/1.0/reference/structure/keyword/

The source code of the plugin is here, works perfectly from NetBeans IDE 7.1 onwards, if all you want is file templates, syntax coloring, and code completion:

https://java.net/projects/nb-api-samples/sources/api-samples/show/versions/7.1/misc/Ceylon

Monday Jul 08, 2013

Electromagnetic Simulation Integration Platform on the NetBeans Platform

ZEBRA is an integration platform for electromagnetic simulations created and used internally at EADS. It provides transverse tools such as a 3d viewer (based on VTK), geometry import and cleaning tools, meshing algorithms, and electromagnetic parameter settings.

The goal is to empower the user with an effective methodology for then exporting a simulation to a preferred native solver that will run either locally or on a high performance cluster.

As stated above, several modules are made available:

  • Geometry module
    • Import DMU with product structure
    • Filtering / Localisation / Selection
    • Idealization / De-featuring
    • Cleaning (Remove overlap, stitching, feature removal , ...)
  • Business module
    • Link with electrical design tool (SEE-Topology)
    • Automated bundle optimisation
    • Automated network generation
    • View / Filtering through functional data
  • Meshing module
    • Cartesian meshing tool
    • Quality mesh check
    • Alternative for mesh reparation
    • Triangular Surfacic Remesh (amibe)
    • Metric definitions: (mesh size , size cartography , combination of analytic functions)
  • Solver module
    • Business electromagnetic parameter definition
    • Interface to multiple electromagnetic solvers (FTDT, BEM, ...)

Sunday Jul 07, 2013

Key Binding & Code Template Viewer

Did you know that Ctrl-Shift-C (as well as Ctrl-/) toggles comments in a Java file, i.e., adds/removes two forward slashes? I didn't know that until browsing through my new Key Bindings viewer:

To see the viewer above in the context of the whole IDE, click the image above.

Want to try it too? Together with the Code Templates viewer shown in this blog yesterday, you can try out the above by installing the plugin here, which you can install into NetBeans IDE 7.3.1:

http://plugins.netbeans.org/plugin/49660/?show=true

You'll see that I tried to convert the strange notations, e.g, "DS-A" to their human readable equivalents, e.g., "Ctrl-Shift-A", though haven't completed that yet. Also, the viewers are not updated when you change the code templates and keybindings in the Options window. That's a feature for the next version of the plugin, shouldn't be hard via a FileChangeListener.

Saturday Jul 06, 2013

View Code Templates While Coding

Sometimes handy to know the code templates NetBeans IDE makes available while you're coding. Click the image below to see the full effect, i.e., the full list of code templates next to the Java editor:

Here's the code:

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.IntrospectionException;
import java.io.IOException;
import java.util.List;
import javax.swing.JButton;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.explorer.ExplorerManager;
import org.openide.explorer.view.OutlineView;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.BeanNode;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.openide.util.lookup.Lookups;
import org.openide.windows.IOProvider;
import org.openide.windows.InputOutput;
import org.openide.windows.OutputWriter;
import org.openide.windows.TopComponent;
import org.openide.xml.XMLUtil;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

@TopComponent.Description(
        preferredID = "CodeTemplatesViewer",
        persistenceType = TopComponent.PERSISTENCE_ALWAYS)
@TopComponent.Registration(
        mode = "properties",
        openAtStartup = true)
@ActionID(
        category = "Window",
        id = "org.netbeans.printtemplates.CodeTemplatesViewer")
@ActionReference(
        path = "Menu/Window")
@TopComponent.OpenActionRegistration(
        displayName = "#CTL_CodeTemplatesAction",
        preferredID = "CodeTemplatesViewer")
@NbBundle.Messages({
    "CTL_CodeTemplatesAction=Show Code Templates",
    "CTL_CodeTemplatesViewer=Available Code Templates",
})
public class CodeTemplatesViewer extends TopComponent implements ExplorerManager.Provider, ActionListener {

    private ExplorerManager em = new ExplorerManager();

    public CodeTemplatesViewer() {
        setName(Bundle.CTL_CodeTemplatesViewer());
        setLayout(new BorderLayout());
        OutlineView outlineView = new OutlineView("Abbreviation");
        outlineView.getOutline().setRootVisible(false);
        outlineView.setPropertyColumns("content", "Content");
        add(outlineView, BorderLayout.CENTER);
        JButton printButton = new JButton("Print");
        printButton.addActionListener(this);
        add(printButton, BorderLayout.NORTH);
        em.setRootContext(new AbstractNode(Children.create(new LanguageChildFactory(), false)));
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        InputOutput io = IOProvider.getDefault().getIO("Code Templates", true);
        io.select();
        OutputWriter out = io.getOut();
        for (Node node : em.getRootContext().getChildren().getNodes()) {
            out.println("");
            out.println("");
            out.println("MIME TYPE: " + node.getDisplayName());
            out.println("");
            for (Node templateNode : node.getChildren().getNodes()) {
                CodeTemplate ct = templateNode.getLookup().lookup(CodeTemplate.class);
                String abbreviation = ct.getAbbreviation();
                String content = ct.getContent();
                out.println(abbreviation+" = "+content);
            }
            out.println("-------------------------------------------");
            out.println("");
            out.println("");
        }
    }

    private class LanguageFolder {
        private String name;
        private String folder;
        public LanguageFolder(String name, String folder) {
            this.name = name;
            this.folder = folder;
        }
        public String getFolder() {
            return folder;
        }
        public void setFolder(String folder) {
            this.folder = folder;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
    }

    private class LanguageChildFactory extends ChildFactory<LanguageFolder> {
        @Override
        protected boolean createKeys(List<LanguageFolder> list) {
            FileObject[] textFolder = FileUtil.getConfigFile("Editors/text").getChildren();
            for (FileObject fileObject : textFolder) {
                FileObject codeTemplatesFolder = fileObject.getFileObject("CodeTemplates/Defaults");
                if (codeTemplatesFolder != null) {
                    list.add(new LanguageFolder(fileObject.getName(), codeTemplatesFolder.getPath()));
                }
            }
            return true;
        }
        @Override
        protected Node createNodeForKey(LanguageFolder key) {
            AbstractNode an = new AbstractNode(Children.create(new CodeTemplateChildFactory(key), false));
            an.setDisplayName(key.getName());
            an.setShortDescription(key.getFolder());
            return an;
        }
    }

    private class CodeTemplateChildFactory extends ChildFactory<CodeTemplate> {
        private final LanguageFolder key;
        private CodeTemplateChildFactory(LanguageFolder key) {
            this.key = key;
        }
        @Override
        protected boolean createKeys(List<CodeTemplate> list) {
            FileObject[] codeTemplateFiles = FileUtil.getConfigFile(key.getFolder()).getChildren();
            for (FileObject fileObject : codeTemplateFiles) {
                try {
                    Document doc = XMLUtil.parse(new InputSource(fileObject.getInputStream()), true, true, null, null);
                    NodeList cts = doc.getElementsByTagName("codetemplate");
                    for (int i = 0; i < cts.getLength(); i++) {
                        org.w3c.dom.Node node = cts.item(i);
                        String value = node.getAttributes().item(0).getNodeValue();
                        StringBuilder sb = new StringBuilder();
                        NodeList childNodes = node.getChildNodes();
                        for (int j = 0; j < childNodes.getLength(); j++) {
                            org.w3c.dom.Node item = childNodes.item(j);
                            sb.append(item.getTextContent());
                        }
                        list.add(new CodeTemplate(value, sb.toString().trim()));
                    }
                } catch (IOException ex) {
                    Exceptions.printStackTrace(ex);
                } catch (SAXException ex) {
                    Exceptions.printStackTrace(ex);
                }
            }
            return true;
        }
        @Override
        protected Node createNodeForKey(CodeTemplate key) {
            TemplateNode node = null;
            try {
                node = new TemplateNode(key);
            } catch (IntrospectionException ex) {
                Exceptions.printStackTrace(ex);
            }
            return node;
        }
    }

    private class TemplateNode extends BeanNode {
        public TemplateNode(CodeTemplate key) throws IntrospectionException {
            super(key, Children.LEAF, Lookups.singleton(key));
            setDisplayName(key.getAbbreviation());
            setShortDescription(key.getContent());
        }
    }

    public class CodeTemplate {
        public String abbreviation;
        public String content;
        public CodeTemplate(String abbreviation, String content) {
            this.abbreviation = abbreviation;
            this.content = content;
        }
        public String getAbbreviation() {
            return abbreviation;
        }
        public String getContent() {
            return content;
        }
        public void setAbbreviation(String abbreviation) {
            this.abbreviation = abbreviation;
        }
        public void setContent(String content) {
            this.content = content;
        }
    }

    @Override
    public ExplorerManager getExplorerManager() {
        return em;
    }

}

Thursday Jul 04, 2013

Print File Templates to Output Window

Here's how to show a dialog listing the folders and files of the Templates folder.

When OK is clicked in the dialog, all the templates in the selected folder are printed to the Output window.

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Collections;
import java.util.Enumeration;
import javax.swing.JPanel;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionRegistration;
import org.openide.explorer.ExplorerManager;
import org.openide.explorer.view.BeanTreeView;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.nodes.FilterNode;
import org.openide.nodes.Node;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle.Messages;
import org.openide.windows.IOProvider;
import org.openide.windows.InputOutput;
import org.openide.windows.OutputWriter;

@ActionID(
        category = "File",
        id = "org.netbeans.printtemplates.PrintTemplatesAction")
@ActionRegistration(
        displayName = "#CTL_PrintTemplatesAction")
@ActionReference(path = "Menu/File", position = 0)
@Messages("CTL_PrintTemplatesAction=Print Templates")
public final class PrintTemplatesAction implements ActionListener {

    private ExplorerManager em = new ExplorerManager();

    @Override
    public void actionPerformed(ActionEvent e) {
        DialogDescriptor dd = new DialogDescriptor(
                new SelectorPanel(), "Select Category", true, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (e.getSource() == DialogDescriptor.OK_OPTION) {
                    OutputWriter writer;
                    InputOutput io = IOProvider.getDefault().getIO("Selected Templates", true);
                    io.select();
                    writer = io.getOut();
                    Node[] selectedNodes = em.getSelectedNodes();
                    for (Node node : selectedNodes) {
                        Enumeration children =
                                node.getLookup().lookup(FileObject.class).getChildren(true);
                        for (FileObject fileObject : Collections.list(children)) {
                            if (!fileObject.isFolder()) {
                                try {
                                    writer.println(DataObject.find(
                                      fileObject).getNodeDelegate().getDisplayName());
                                } catch (DataObjectNotFoundException ex) {
                                    Exceptions.printStackTrace(ex);
                                }
                            }
                        }
                    }
                }
            }
        });
        DialogDisplayer.getDefault().createDialog(dd).setVisible(true);
    }

    private class SelectorPanel extends JPanel implements ExplorerManager.Provider {

        public SelectorPanel() {
            setLayout(new BorderLayout());
            setPreferredSize(new Dimension(400, 400));
            add(new BeanTreeView(), BorderLayout.CENTER);
            try {
                em.setRootContext(
                        new FilterNode(DataObject.find(
                        FileUtil.getConfigFile("Templates")).getNodeDelegate()));
            } catch (DataObjectNotFoundException ex) {
                Exceptions.printStackTrace(ex);
            }
        }

        @Override
        public ExplorerManager getExplorerManager() {
            return em;
        }

    }

}

Wednesday Jul 03, 2013

New File Without Project

The upcoming NetBeans Platform 7.4 @TemplateRegistration attribute requireProject is handy when you want to display a file template in the New File dialog when you have no project that relates to it. However, what if you not only have no related project but no interest in the NetBeans project system at all? Then you have a problem because you need the NetBeans project APIs if you want to have the New File dialog because the New File dialog classes are found in the modules that define the NetBeans project system. Lots of menus and toolbar buttons are added to your application for free, superfluously, and you spend time hiding them while at the same time the user gets a bunch of JARs that are not needed at all. Though the coupledness between projects and files makes complete sense from the perspective of NetBeans IDE, it would be nice if the New File dialog were to be in its own separate module from the perspective of non-project oriented NetBeans Platform applications.

A simple workaround is to forget the New File dialog completely, because of above stated dependencies on the project system, and create your own. Even simpler is to create a bunch of simple actions that create new files for you, which means that the whole project infrastructure isn't needed at all.

Here's an example, with thanks to the NetBeans Ribbon Bar project, provided by Chris Bohme from the awesome Maltego team.

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;
import org.netbeans.api.actions.Openable;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionRegistration;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileSystem;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataFolder;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle.Messages;

@ActionID(
        category = "File",
        id = "org.squibbly.file.odp.NewFile")
@ActionRegistration(
        displayName = "#CTL_NewFile")
@ActionReference(
        path = "Menu/File", 
        position = 0)
@Messages("CTL_NewFile=New File")
public final class NewFileAction implements ActionListener {

    private static AtomicInteger _integer = new AtomicInteger(0);

    @Override
    public void actionPerformed(ActionEvent e) {
        try {
            DataObject gdo = getDataObject();
            Openable openable = gdo.getLookup().lookup(Openable.class);
            openable.open();
        } catch (DataObjectNotFoundException ex) {
            Exceptions.printStackTrace(ex);
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }
    }
    
    protected DataObject getDataObject() throws DataObjectNotFoundException, IOException {
        String templateName = getTemplate();
        FileObject fo = FileUtil.getConfigRoot().getFileObject(templateName);
        DataObject template = DataObject.find(fo);
        FileSystem memFS = FileUtil.createMemoryFileSystem();
        FileObject root = memFS.getRoot();
        DataFolder dataFolder = DataFolder.findFolder(root);
        DataObject gdo = template.createFromTemplate(
               dataFolder, 
               "New Document" + " (" + getNextCount() + ")");
        return gdo;
    }

    protected String getTemplate() {
        return "Templates/Other/file";
    }

    private static int getNextCount() {
        return _integer.incrementAndGet();
    }
    
}

You'd create one of the above for each type of document you'd like the user to be able to create. Note that "getTemplate" above, which points to the location in the filesystem where you've registered your template, probably thanks to the @TemplateRegistration annotation.

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
« July 2013 »
SunMonTueWedThuFriSat
 
5
10
14
21
27
28
29
30
31
   
       
Today