Download NetBeans!

20090630 Tuesday June 30, 2009

Three NetBeans Platform Applications You Never Knew Existed

Right now, as we speak [type], I am working on articles/interviews relating to three applications on the NetBeans Platform... none of which anyone in the broader NetBeans Platform community knows about. So, to give you a sneak preview, here they are, with a little bit of background info on each. (Not too much info, otherwise why would you want to read the completed article/interview?)

First of all, I present... a financial application, which is created in Brazil, by Paulo Canedo, and a team of developers around him, who work for the Tribunal de Contas do Estado do Tocantins, a state in Brazil, where all the financial management related to the state is done on the NetBeans Platform. The application was started in 2007 and, in particular, Paulo's team likes the wizard framework of the NetBeans Platform, as well as the update center. Combined, these features enable the application to be responsible for all finances in the city, i.e., purchases and payments. The application processes data via XML and then transforms and stores in a Derby database. Furthermore, the application is used to analyze the data thus obtained and stored.

And here is a sneak preview screenshot (more in an upcoming article):

Next, an application by Ingmar Hendriks, and others, who are students at the Hogeschool van Amsterdam. Not very long ago, they completed a NetBeans Platform Certified Training. (My blog entry "Amsterdam on the NetBeans Platform" tells you all about it.) Ingmar's graduation project was to create a sensor monitoring application. He had to make two programs, a server and a client. Because he didn't have a whole laboratory full of sensors at school, he had to simulate the sensors by generating random values within a certain parameter. The generation of these random values had to be done on the server, with a time interval of a few hundred milliseconds and the server needed to store these values. This itself sounds very doable until you realize that over 400 sensors had to be simulated, each with an interval of a few hundred milliseconds and that these had to be stored into memory and not on the hard drive.

In order to achieve this, the memory had to be controlled, which is not possible with Java because you have no control over memory management... so C++ had to be used. The client, however, was a different story. It only needed to access the values of a sensor and show them in a chart. If a value on the server exceeded its preset safety parameter, it needed to show a warning or error in the client. Here's a sneak preview screenshot of the application that resulted from all of this:

And, finally, let's take a look at Central Washington University's programming tools for the blind that, hopefully, will make them more accessible. These tools are very complicated, as they involve custom compilers, debuggers, and sound architectures. These architectures then need to be built into standard IDEs.

Here is a screen capture of the environment as a whole, annotated with details of what was added at Central Washington University. Notice that, while the screen capture looks just like NetBeans IDE, what has been added is a new programming language (Hop). In addition, the debugger is "omniscient", which means that you can execute code forward and backward. For example, in most debuggers, you can click "Continue" (the green button) and step the code to the next breakpoint. In this debugger, you can also "Rewind" (the blue button) to the previous breakpoint. Similarly, most IDEs let you step over a line of code. This one also lets you step back:

What do these applications gain from being based on the NetBeans Platform? Modularity (i.e., you can create plugins for these applications), while being based on Swing (the standard UI toolkit). That's a combination that no other framework provides natively. Typically, a developer using the NetBeans Platform begins by appreciating the NetBeans Platform's Swing extensions, such as the window system and explorer views. Later, the modularity becomes increasingly useful, both from the side of development (i.e., encapsulate code on a level higher than packages, which makes it easier to create work areas for distributed development teams) and from the side of deployment (i.e., the end user is able to extend the application, by means of plugins, without needing to download/understand the entire codebase).

But, of course, this is simply the tip of the iceberg. To find out about several other NetBeans Platform applications, click here and browse through the whole showcase. Several known applications on the NetBeans Platform cannot be advertized, i.e., must remain secret, since they're the basis of, for example, military or financial systems whose underlying technologies cannot be made public. In many ways, that's a pity, because the full length and breadth of NetBeans Platform usage will probably never be known.

Want to advertize your application on the NetBeans Platform? For free? Drop me an e-mail at geertjan DOT wielenga AT sun DOT com and it will be given all the attention you desire (plus more).

Jun 30 2009, 02:28:03 PM PDT Permalink

Download NetBeans!

20090629 Monday June 29, 2009

Back from Brazil: Hello NetBeans IDE 6.7

I'm back from FISL in Brazil! Too many highlights to do justice to—experiencing presentations by Richard Stallman, Simon Phipps, and Peter Sunde was certainly one of them. Another was being in Brazil at all, of course. Anyway, I summarized it for anyone who'd like to know my take on what happened there (or, at least, to find out what kind of things I personally experienced):

What I found especially interesting about FISL was the focus on copyright / human rights law, as much as on technology itself. In other words, more often than not, the speaker would not do any demonstrations at all, nor talk about what wonderful things their company is doing. Instead, they'd talk about the current state of cybercrime legislation as it pertains to some area or other (see the above links for details).

My award for most inspiring presenter goes to Peter Sunde (Wikipedia entry). My award for most eccentric presenter goes to Richard Stallman (Wikipedia entry). From both I learned an incredible amount. See part 2 above, for all the details.

I had my own few minutes to tell my tale, in a presentation on Saturday entitled "Java Development: Beyond the IDE". Basically, it was all about how NetBeans IDE 6.7 raises the bar when it comes to what an IDE is able to do. For the first time, with NetBeans IDE 6.7, an IDE is able to manage your project beyond the create/edit/deploy/debug cycle: you can also store it (for free) in a source code repository, assign issues to it, retrieve the source code, and chat to other team members... all inside the same IDE where you did your coding! Uniqueness was never this unique.

Here's my presentation (though the majority was a demo, so you won't see much in the slides):

BeyondTheIDE.odp (OpenOffice)

And here's a pic of me presenting the agenda of the presentation:

The above entails that I demoed Kenai.com, GlassFish, MySQL, and VisualVM, in addition to NetBeans IDE. Of course, I ended by summarizing the main enhancements in 6.7:

By the way:

Download NetBeans IDE (for free!) here.

A lot of cool reactions afterwards. Attendees were amazed at how responsive NetBeans is and how many features it has out of the box. The first pic above was taken by Arun Gupta, the second by Eros Stein. He's a NetBeans user I mentioned in the 3rd part of my articles listed above. It was great to meet him. In terms of creating a community around a product, nothing beats talking to a user face to face!

Thanks for the great time at FISL. Especially to the Sun Campus Ambassadors who were there. They were great.

Jun 29 2009, 10:17:12 AM PDT Permalink

Download NetBeans!

20090623 Tuesday June 23, 2009

Kafka at the Airport: Why Online Check-in is a Myth

"Ha," you think, as you click your way through an online check-in form. "I will not need to wait in those long lines, since I'll already have my boarding card. That's especially cool since there's only one hour between my arrival and my transfer to the next point in my trip."

And so, ignorant of the great delusion that is about to reveal itself to you, you slip the freshly printed boarding cards into your passport. Next day, everything starts promising. Your first flight bears you no ill will and before you know it you're at the next airport, expecting to transfer smoothly to the next flight.

And then it happens. You show your 'boarding card' which, yes, is quickly to receive small quotation marks around itself, and are brusquely told to complete the check-in process. What check-in process?! You've already checked in! The Kafkasque world that is the online check-in lie gradually exposes itself, as you find yourself in an ever increasing frenzy, frantically trying to make sense of the world as you know it, while the plane that should be carrying you off to your final destination threatens to take off without you.

All this is because online check-in is a farce, for (at least) the following three reasons:

  • Security. The powers that be can't check whether you're a suspect person (whatever that term means to you) if you're checking in online. Therefore, as I discovered when flying from San Francisco to Frankfurt recently, I needed to check-in in person so that whatever checks they do could be done. The funny thing was that they'd set up a special line for people who had already checked-in online, but since so many people had done exactly that... the 'online check-in check-in line' was longer than the line for those who hadn't checked-in online at all.

  • Carry-on luggage variations. On some types of planes, i.e., large ones, carry-on luggage limits are determined by the size of the luggage. I.e., those small wheeled suitcases that everyone seems to have nowadays (in order to keep your belongings as close to you as possible and circumventing long waits at the luggage conveyor belt and the ever looming possibility of lost luggage) are acceptable on large planes. However, on small planes they want you to check those in, i.e., not carry them on to the plane, unless they weigh less than 5kg (and, seriously, is there one of those little suitcases that isn't crammed with everything you could possibly cram into it, all of which is always going to be over 5kg)? That's what happened on my flight today in Brazil from Sao Paolo to Porto Alegre.

  • Ignorance. Not all employees at airports seem to be aware that there is such a thing as online check-in.

So, because of the above reasons (and probably others) the online check-in procedure is a complete farce. At its very best, the procedure is useful in reserving your seat. But not for checking in! Although, sometimes it DOES work as check-in process, which is even WORSE because you never know until the nice looking lady casts her cold eyes of death over you, as you stand their quivering and pleading to be let through because after all you have every right... since you CHECKED-IN ALREADY.

Jun 23 2009, 07:41:26 AM PDT Permalink

Download NetBeans!

20090622 Monday June 22, 2009

Developing for Google App Engine in NetBeans IDE

One of the many people I met at JavaOne was NetBeans Platform developer Mark Claassen. (I'd still like to interview him about his NetBeans Platform experiences, just like I did with Chad Dorkin, as evidenced in the interview published yesterday entitled "Semiconductor Validation Engineering on the NetBeans Platform".)

Mark was concerned that NetBeans IDE seemed to be missing a number of very crucial plugins or that those plugins had not been adequately advertized. Here's my attempt to rectify that situation for one specific plugin, the one for developing/deploying Java applications for the Google App Engine:

http://plugins.netbeans.org/PluginPortal/faces/PluginDetailPage.jsp?pluginid=18493

I also created an issue on the Google App Engine site for missing documentation relating to this NetBeans plugin:

http://code.google.com/p/googleappengine/issues/detail?id=1734

Feel free to add your support for this issue above.

Now a quick overview of what the plugin entails. First, of course, you need to download, unzip, and then install the NBM files that the plugin provides:

Next, you'll find you have the complete sample that is outlined on the Google App Engine site, i.e.. a Guest Book:

Also, the Google App Engine configuration file has a special icon, file support, and a visual editor:

The Services window shows a node for the running Google App Engine, which I was able to register after downloading the Java bundle for the Google App Engine:

Whenever you create a new web application, you can specify that it should be deployed to the Google App Engine, which causes the abovementioned Google App Engine configuration file to be created for you when Finish is clicked in this wizard:

And, once your application is ready to be deployed, you can right-click it and then upload it to the Google App Engine from inside the IDE:

That's a pretty solid plugin, providing exactly the kind of Google App Engine support that I'd expect NetBeans IDE to have. The only questions are when this will be mentioned on the Google App Engine site and when the plugin will be part of a standard NetBeans IDE release.

Go here to look at the sources, join the developer community around this project, or contribute source code yourself:

http://kenai.com/projects/nbappengine

Jun 22 2009, 02:04:14 AM PDT Permalink

Download NetBeans!

20090619 Friday June 19, 2009

NetBeans Client for Bugzilla Issue Tracking

I added some issues to the NetBeans MigLayout project today, using NetBeans IDE:

Then I went to the site on-line and saw that everything had been done as I'd have expected it to:

Pretty handy, being able to handle that, as well as view my issues and so on, from inside the IDE.

The only strange thing is the ID number. I'd have expected them to start at 1, instead of 522.

Jun 19 2009, 08:12:11 AM PDT Permalink

Download NetBeans!

20090618 Thursday June 18, 2009

Me at FISL

I'm going to be at FISL in Brazil next week:

Hope to see you there!

Jun 18 2009, 11:34:47 AM PDT Permalink

Download NetBeans!

20090617 Wednesday June 17, 2009

Results of the NetBeans Platform Student Quiz 3

The series of quizes especially for those who have taken the NetBeans Platform Certified Training has now reached its third edition. Click here for part 1 and click here for part 2.

And here is part 3, the questions and the answers, followed by the winners of this quiz. Each of the quizes has a theme. This time, the theme was 'Useful Links for NetBeans Platform Developers'. Therefore, if you're developing on top of the NetBeans Platform, you're bound to find a couple of links below that you didn't know about before!

  1. I was told that the API of a particular NetBeans class was updated last week. What's the URL I need to look at to find all the latest API modifications?

    http://bits.netbeans.org/dev/javadoc/apichanges.html

  2. I was told that the solution to my problem was found on the mailing list for NetBeans Platform developers. What's the URL for that archive?

    http://openide.netbeans.org/servlets/SummarizeList?listName=dev

  3. I've been told about a 4-part tutorial that covers the NetBeans Lookup class, as well as the Node class, in some detail. What's the URL for the first part?

    http://platform.netbeans.org/tutorials/nbm-selection-1.html

  4. I've been told that UNESCO is doing some cool things with the NetBeans Platform. What's the URL for that story?

    http://netbeans.dzone.com/news/unesco-netbeans-platform

  5. There's a funny picture of a big sandwich that represents the NetBeans virtual filesystem, which comes from someone's blog. What's the exact URL pointing to the blog entry containing the image of the sandwich?

    http://antonioshome.net/kitchen/netbeans/nbms-sandwich.php

  6. There's a PHD student in Linz, Austria, who has created a series of lectures about the NetBeans Platform. What's the URL pointing to the lecture series?

    http://www.ssw.uni-linz.ac.at/Teaching/Lectures/SpezialLVA/TulachWielenga/index.html

  7. The "Definitive Guide to the NetBeans Platform", a book by Tim Boudreau and Jesse Glick, which includes a big section on the NetBeans Platform, is still available on-line. What's the URL to the whole book?

    http://www.netbeans.org/download/books/definitive-guide/index.html

  8. What's the URL of a blog full of interesting NetBeans Platform tips, especially around localization and branding, written by a developer based in Indonesia?

    http://blogs.kiyut.com/tonny/

  9. What's the URL pointing to a list of issues in Issuezilla that are specifically marked as being good ones for external contributors (such as NetBeans Platform students) to fix?

    http://www.netbeans.org/issues/buglist.cgi?status_whiteboard=request_for_contribution&status_whiteboard_type=substring

  10. What's the home page of the NetBeans Platform?

    http://platform.netbeans.org/

And the winners are:

  • First Prize: Bartek Zdanowski (Poland)

  • Second Prize: Jiří Jakeš (Czech Republic)

And a pic of the prizes:

Congratulations! Bartek wins The Definitive Guide to NetBeans Platform, while Jiří gets a t-shirt and pen! And also congratulations to everyone else who entered. You'll all receive a small surprise by mail in the coming weeks.

Jun 17 2009, 05:42:31 AM PDT Permalink

Download NetBeans!

20090616 Tuesday June 16, 2009

Registering MigLayout in NetBeans IDE 6.7

I started creating a small module that integrates MigLayout into the IDE. That won't help Groovy developers at all, since the GUI Builder generates Java code (and that is unlikely to change). However, it will help Java developers who want to use MigLayout as their LayoutManager.

Already a couple of things are possible—when you create a Swing container in the Matisse GUI Builder, you can set MigLayout as your LayoutManager:

You'll find you have a new node for the layout you chose:

Then you'll also find the MigLayout JAR in the application's Libraries node, which indicates that it has been put on your classpath. In addition, the "initComponents" of a JFrame now has this content:

private void initComponents() {

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
    getContentPane().setLayout(new net.miginfocom.swing.MigLayout());

    pack();
}

If you add a JPanel, the "initComponents" ends up like this:

 private void initComponents() {

    jPanel1 = new javax.swing.JPanel();
    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
    getContentPane().setLayout(new net.miginfocom.swing.MigLayout());

    jPanel1.setLayout(new net.miginfocom.swing.MigLayout());
    getContentPane().add(jPanel1);

    pack();
}

You can tweak the Options window to not have the FQN generated. It's early days yet, so you can't add the MigLayout constraints yet (e.g., "wrap" and so on). Plus, the above are blue blocks, so you can't even add those constraints manually at this point. Also, the typical Matisse GUI Builder features such as align and resize and so on are not supported. All that's currently available is the registration of the MigLayout library and the ability to graphically add it to your project, together with code generation for setting the LayoutManager via the same graphical function.

The source code can be found here on Kenai:

http://kenai.com/projects/nbmiglayout/

If you have ideas about how the user should be able to graphically set MigLayout constraints, probably via drag-and-drop, I guess, feel free to join the project and share your ideas.

Jun 16 2009, 10:25:34 AM PDT Permalink

Download NetBeans!

20090615 Monday June 15, 2009

Use Maven? You'll Love NetBeans IDE 6.7!

During the time I spent doing demos at the NetBeans Booth during JavaOne, each and every Maven user I spoke to was amazed when I showed them this:

That POM dependency graph feature is part of NetBeans IDE 6.7. And how much does it cost? Nothing at all. "And that's a pretty good price," someone told me when I showed them the above...

In other news. Click here to listen to a 20 minute radio show at JavaOne where Tori Wieldt interviews me about upcoming features in NetBeans IDE 6.7.

Jun 15 2009, 10:09:35 AM PDT Permalink

Download NetBeans!

20090614 Sunday June 14, 2009

How to Incorporate a Wizard into a Griffon Application (Part 4)

Thanks to an intervention by Andres Almiray, I now have the Griffon wizard/db example working as I'd expect it to. The wizard's first step is filled from a database, when a selection is made in the drop-down two labels below it are updated with additional info about the current selection:

Here's the code, especially the parts in bold:

import net.miginfocom.swing.MigLayout
import ca.odell.glazedlists.*
import javax.swing.event.ListSelectionListener
import java.util.Map
import ca.odell.glazedlists.swing.EventSelectionModel
import ca.odell.glazedlists.swing.EventListModel

class OneWizardPage {

    def stepId = "step1" // must be unique per WizardPage
    def description = "Customer Details"
    def autoListen = true

    def selCity = '<empty>'
    def selState = '<empty>'

    def pageContents = {

        EventList namesEventList = new BasicEventList()
        namesEventList.addAll( MyDbService.instance.getAllNames() )

        EventListModel listModel = new EventListModel(namesEventList)

        EventSelectionModel selectionModel = new EventSelectionModel(namesEventList)
        def cityLabel = null
        def stateLabel = null
        selectionModel.addListSelectionListener( [ valueChanged: {e ->
                    if (e.valueIsAdjusting){
                        def customer = selectionModel.selected
                        doOutside {
                            selCity = MyDbService.instance.getCityForSelectedName(customer)
                            selState = MyDbService.instance.getStateForSelectedName(customer)
                            doLater { 
                                cityLabel.text = selCity
                                stateLabel.text = selState
                            }
                        }
                    }
                } ] as ListSelectionListener)

        panel(border:lineBorder(1, color: java.awt.Color.black), constraints: "growx", layout: new MigLayout('fill')) {

            label( text: "Name:" )
            scrollPane(constraints: "growx, wrap"){
                list( name: "tf1", model: listModel, selectionModel: selectionModel, visibleRowCount: 1 )
            }
            label( text: "City:" )
            cityLabel = label( name: "tf2",
                text: selCity,
                constraints: "growx, wrap" )
            label( text: "State:" )
            stateLabel = label( name: "tf3",
                text: selState, 
                constraints: "growx, wrap" )

        }

    }

    // Either return a String that indicates a problem
    // or return a null value indicating no problem
    def onValidate = { component, /*PropertyChangeEvent*/ event ->
        return null // no problems
    }

}

Thanks Andres!

Jun 14 2009, 05:16:53 AM PDT Permalink

Download NetBeans!

20090612 Friday June 12, 2009

How to Incorporate a Wizard into a Griffon Application (Part 3)

I've solved several problems I had with integrating a db into a Griffon wizard, with this result:

In other words, though I can successfully populate a drop-down list with customer names and put related city and state information into the output, I am unable to bind that output to the related text fields. I wonder how the @Bindable annotation works in the context of wizards. Or maybe it should be solved in a different way.

Here's conf/DataSource.groovy:

dataSource {
    url = "jdbc:derby://localhost:1527/sample"
    driverClassname = "org.apache.derby.jdbc.ClientDriver"
    username = "app"
    password = "app"
}

Here's conf/Events.groovy:

onBootstrapEnd = { app ->
   def dataSource = new ConfigSlurper().parse(DataSource).dataSource
   MyDbService dbs = MyDbService.instance
   dbs.initDataSource(dataSource)
}

Here's services/MyDbService.groovy:

import groovy.sql.Sql

@Singleton
class MyDbService {
    
    private sql

    def initDataSource( dataSource ) {
        sql = Sql.newInstance(
            dataSource.url,
            dataSource.username,
            dataSource.password,
            dataSource.driverClassname
        )
    }

    def getAllNames() {
        sql.rows("select * from APP.CUSTOMER").NAME
    }

    def getCityForSelectedName(String selectedName) {
        sql.firstRow("select CITY from APP.CUSTOMER where NAME = ${selectedName}").CITY
    }

    def getStateForSelectedName(String selectedName) {
        sql.firstRow("select STATE from APP.CUSTOMER where NAME = ${selectedName}").STATE
    }
  
}

And, finally, here's wizards/OneWizardPage.groovy, where the change in 'selCity' should be reflected in the City text field. Both parts are highlighted below.

import net.miginfocom.swing.MigLayout
import ca.odell.glazedlists.*
import javax.swing.event.ListSelectionListener
import java.util.Map
import ca.odell.glazedlists.swing.EventSelectionModel
import ca.odell.glazedlists.swing.EventListModel

class OneWizardPage {

    def stepId = "step1" // must be unique per WizardPage
    def description = "Customer Details"
    def autoListen = true

    def selCity = '<empty>'
    def selState = '<empty>'

    def pageContents = {

        EventList namesEventList = new BasicEventList()
        namesEventList.addAll( MyDbService.instance.getAllNames() )

        EventListModel listModel = new EventListModel(namesEventList)
  
        EventSelectionModel selectionModel = new EventSelectionModel(namesEventList)
        selectionModel.addListSelectionListener( [ valueChanged: {e ->
                    if (e.valueIsAdjusting){
                        def customer = selectionModel.selected
                        selCity = MyDbService.instance.getCityForSelectedName(customer)
                        selState = MyDbService.instance.getStateForSelectedName(customer)
                        println "${customer} from ${selCity} (${selState})"
                    }
                } ] as ListSelectionListener)

        panel(border:lineBorder(1, color: java.awt.Color.black), layout: new MigLayout('fill')) {

            label( text: "Name:" )
            scrollPane(constraints: "growx, wrap"){
                list( name: "tf1", model: listModel, selectionModel: selectionModel, visibleRowCount: 1 )
            }
            label( text: "Address:" )
            cityField = textField( name: "tf2",
                text: selCity,
                columns: 20, constraints: "wrap" )
            label( text: "City:" )
            textField( name: "tf3", text: "", columns: 20 )

        }

    }

    // Either return a String that indicates a problem
    // or return a null value indicating no problem
    def onValidate = { component, /*PropertyChangeEvent*/ event ->
        return null // no problems
    }

}

Can anyone help?

Jun 12 2009, 11:58:41 PM PDT Permalink

Download NetBeans!

20090609 Tuesday June 09, 2009

How to Incorporate a Wizard into a Griffon Application (Part 2)

Let's make the Griffon wizard a bit more realistic than in yesterday's example.

  1. Use the same approach as outlined yesterday to create a second panel in the wizard. When prompted for a name, type "Two".

  2. In the controller, change the action to the following:
    def action = { evt = null ->
            def wizard = wizard( title: "Customer Order Wizard", pages: ["One", "Two"], resultProducer: [
                    //The Cancel button cancels:
                    cancel: { settings ->
                        return true
                    },
                    //Not sure what the 'data' is for:
                    finish: { data ->
                        return data
                    }
                ] )
            def result = showWizard(wizard)
            view.ta.text =
    """
    Name: ${result.tf1}
    Address: ${result.tf2}
    City: ${result.tf3}
    
    Order
    --------------------------
    ID: ${result.tf4}
    Name: ${result.tf5}
    Description: ${result.tf6}
    """
    
    }

    Note: The triple quotation marks are Groovy string concatenators, replacing the + construction common to Java.

  3. Add the MigLayout JAR (easy way to get it is to look at the Griffon 'Greet' example) to your application classpath.

  4. Change the "OneWizardPage.groovy" (in "griffon-app/wizards") to the following:
    import net.miginfocom.swing.MigLayout
    
    class OneWizardPage {
    
        def stepId = "step1" // must be unique per WizardPage
        def description = "Customer Details"
        def autoListen = true
    
        def pageContents = {
            panel(border:lineBorder(1, color: java.awt.Color.black), layout:new MigLayout('fill')) {
                label( text: "Name:" )
                textField( name: "tf1", text: "", columns: 20, constraints: "wrap" )
                label( text: "Address:" )
                textField( name: "tf2", text: "", columns: 20, constraints: "wrap" )
                label( text: "City:" )
                textField( name: "tf3", text: "", columns: 20 )
            }
        }
    
        // Either return a String that indicates a problem
        // or return a null value indicating no problem
        def onValidate = { component, /*PropertyChangeEvent*/ event ->
            return null // no problems
        }
       
    }

    Note: Hurray for MigLayout, without which you wouldn't have the "constraints" property in the textFields. For further details, read How Griffon Helps MigLayout and MigLayout: Inevitable Choice for Griffon Users? (Another article to look at is Porting to Griffon, though MigLayout isn't used there.)

  5. Next, define the "TwoWizardPage.groovy" (in "griffon-app/wizards") to the following:
    import net.miginfocom.swing.MigLayout
    
    class TwoWizardPage {
       def stepId = "step2" // must be unique per WizardPage
       def description = "Product Details"
       def autoListen = true
    
       def pageContents = {
          panel(border:lineBorder(1, color: java.awt.Color.black), layout:new MigLayout('fill')) {
                label( text: "ID:" )
                textField( name: "tf4", text: "", columns: 20, constraints: "wrap" )
                label( text: "Name:" )
                textField( name: "tf5", text: "", columns: 20, constraints: "wrap" )
                label( text: "Description:" )
                textField( name: "tf6", text: "", columns: 20, constraints: "wrap" )
            }
       }
    
       // Either return a String that indicates a problem
       // or return a null valud indicating no problem
       def onValidate = { component, /*PropertyChangeEvent*/ event ->
          return null // no problems
       }
       
    }

    Note: The textField names are very important. The controller has access to them, via "${result.tf1}" and so on in the action defined in the controller.

  6. Run the application.

    Click the "New" menu item, as before. When you fill out the first step, you should see something like this:

    Notice how the "constraints" property wraps the component after the textFields onto the next line, meaning that we don't need to wish we had something like the Matisse GUI Builder at all. After filling the above out, click Next, fill out the Order form, and you should see something like this:

    Click Finish and here's the result:

What I'm curious about is how to connect my Griffon application to a database. That would make it possible to fill the wizard panels with customer and product data from a database.

Jun 09 2009, 03:19:27 PM PDT Permalink

Download NetBeans!

20090608 Monday June 08, 2009

How to Incorporate a Wizard into a Griffon Application

Let's create a Griffon application that includes a wizard! In the end, you'll have an application, as shown below, with a "New" menu item, which pops up a wizard. When "Finish" is clicked, the text in the wizard is put into the text area in the application:

Here are the steps:

  1. Run "griffon create-app", using "WizardDemo1" when prompted for a name. Or use the "New Griffon Application" template in NetBeans IDE.

  2. Run "griffon list-plugins" and then install the Wizard plugin. Or right-click the application in NetBeans IDE, choose "Griffon Plugins...", and use the New Plugins tab to install the "wizard" plugin (currently the last one in the list). By doing this, you add a new folder, "griffon-app/wizards" and you also have a new scripts available for creating wizard artifacts.

  3. Run "griffon create-wizard-page". Or right-click the application in NetBeans IDE, choose "Run Griffon Command...", choose "create-wizard-page", and choose Run. Type "One" when prompted, which will result in a new file called "OneWizardPage.groovy" in the "griffon-app/wizards" folder.

    The content of "OneWizardPage.groovy" is as follows, none of which you will need to change in this example:

    class OneWizardPage {
       def stepId = "step1" // must be unique per WizardPage
       def description = "Step Description"
       def autoListen = true
    
       def pageContents = {
          // remember to always set a name: property to each input widget
          textField( name: "tf1", text: "Add Content Here" ) 
       }
    
       // Either return a String that indicates a problem
       // or return a null valud indicating no problem
       def onValidate = { component, /*PropertyChangeEvent*/ event ->
          return null // no problems
       }
    }

  4. Change the "WizardDemo1View.groovy", in "griffon-app/views", to the following:
    application(title:'WizardDemo1',  size:[320,200], location:[50,50], locationByPlatform:true) {
        menuBar {
            menuItem('New', actionPerformed:controller.action)
        }
        textArea(id: 'ta','<Empty>')
    }

  5. In line 4 above, you're referring to an action in the "WizardDemo1Controller.groovy", which is in "griffon-app/controllers". Define it like this:
    def action = { evt = null ->
        def wizard = wizard( title: "My Wizard", pages: ["One"] )
        def result = showWizard(wizard)
        view.ta.text = result.tf1
    }

    The "One" in line 2 above refers to the "One" you typed when you created the wizard page. From the "showWizard", you get a result, from which you get "tf1", which is the name of the text field in the wizard page. That's what you put in the text area, which has the id "ta", in the view.

Hurray. You're done. Simple example for one wizard page which, when "Finish" is clicked, causes the content of the wizard to be put in the view's text area. And a lot of this is thanks to Tim's wizard.dev.java.net project, as can be seen from the NetBeans 5.0 splash screen in the left of the wizard shown above.

Jun 08 2009, 03:55:06 PM PDT Permalink

Download NetBeans!

20090606 Saturday June 06, 2009

Me Interviewed by Scott Davis

If you can handle seeing my face staring back at you for half an hour, here's a movie you might like. It's by Scott Davis, the highly respected (and much loved) Groovy expert from ThirstyHead.

Topics discussed in the movie include, but are not limited to, how not to pronounce my name, agile translation, why Groovy is cool, why Griffon is cool, why Kenai is cool, how to create NetBeans modules, how to support Griffon in NetBeans IDE, the purpose of desktop frameworks, and the future of the desktop in general. Hope you have as much fun watching it as Scott and I had making it:

By the way, if you're even slightly interested in Groovy, the book you MUST get is Scott's Groovy Recipes. Buy it. You won't regret it. Several other movies by Scott with Groovy-related people can be found at ThirstyHead.

Jun 06 2009, 12:59:52 AM PDT Permalink

Download NetBeans!

20090605 Friday June 05, 2009

Sun Learning Services Offers NetBeans Platform Training

With literally dozens of cool things having happened in the last few days, it's really hard to pick one topic (which is what I do in this blog, generally) and it's also really hard to blog once per day (which is also what I do). I believe, though, that of the many many things JavaOne related (more of that later) in connection with the NetBeans Platform, the release of the NetBeans Platform course as a standard Sun Learning Services offering is probably the best and most far reaching:

Click the image above to get to the related full description on sun.com.

Firstly, just to be clear, in some ways nothing has changed. If you are some kind of school/university or non-commercial organization, we offer the course to you for free (assuming you're located somewhere where we can get to you easily). Secondly, however, if you're some kind of commercial company, you now—for the first time—have an official Sun course at your disposal. The content of the course is the same as before, with the difference that Sun now officially supports it.

Community trainers, such as Anton Epple and Aljoscha Rittner and other NetBeans Platform Trainers who do not work for Sun are also still supported. In other words, we have a hybrid model whereby Sun offers the above course, providing official Sun staff (such as myself and Jaroslav Tulach and Tim Boudreau and many others) to deliver that course. In addition, we can call in the help of community trainers, who can also be reimbursed for their efforts.

On top of that, the NetBeans Platform trainings offered by the community trainers (i.e., non-Sun employees), such as this one by Eppleton are completely valid too. They simply fall outside of the Sun ecosystem and can function independently, since the NetBeans Platform, as well as all the related training materials are open sourced. In other words, anyone can (and is encouraged to) take the training materials and make money off them. We also have a program for certifying NetBeans Platform trainers, which means Sun will officially endorse you as a trainer, by adding you to the NetBeans Platform Trainers page, so that prospective clients of yours can see that you're qualified to train them.

Finally, all of this means two other important things. Firstly, the NetBeans Platform is now an official part of the Sun Learning Services revenue stream. Secondly, commercial organizations interested in taking the course should now take confidence knowing that Sun officially endorses the NetBeans Platform training. Implicitly, the NetBeans Platform as an area of interest separate from NetBeans IDE is thereby also endorsed.

Jun 05 2009, 07:23:55 AM PDT Permalink