Lesson #1: InvalidDnDOperationException Ruins Sanity

A friend with whom I am currently working on a programming contract called me today to tell me that the latest build wasn’t working. At all.

This irritated and confused me, as I hadn’t worked on that particular project for a week or so, and couldn’t remember having any issues with it.

I booted into Windows (I use Linux mostly), downloaded Eclipse and imported the project.

Sure enough:

java.awt.dnd.InvalidDnDOperationException: Drag and drop in progress
	at sun.awt.dnd.SunDragSourceContextPeer.setDragDropInProgress(Unknown Source)
	at java.awt.dnd.DragSource.startDrag(Unknown Source)

This error had attacked me before, but a quick investigation revealed that the issue was different this time. Joyous news.

I poked about in the (too many) classes that make up this project, but discovered nothing of use.

After some fruitless Googling, it occurred to me that during the great Refactoring Storm of August, I may have changed some of the DragGestureRecognizers’ DnDConstants to ACTION_COPY instead of ACTION_COPY_OR_MOVE.

A short, smaller storm of refactoring esued, during which all ACTION_COPY_OR_MOVE DnDConstants were changed to ACTION_COPY.

Why was this an issue at all? I was using evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); to accept the drops, which I guess I must have assumed would accept an ACTION_COPY drop. Seemed to in Ubuntu, anyway. Maybe the Windows JRE is more strict (re: mental)?

Why this issue hid itself until now, I don’t know. Perhaps Ubuntu just likes me more.

Lesson: test software on the target system BEFORE giving it to your team-members.

No comments | Trackback

Write Your Own Listener Interface (you know you want to)

This tutorial was all I needed to quickly implement my listener: Listeners in Java

It’s clear, succinct and comprehensive. When you need to implement your custom listener interface, check it out.

Comments (3) | Trackback

Java: repaint() Waking Nightmare

I wanted the little app I’m making to display a green tick or a red cross depending on whether the user had entered valid credentials. Simple? Yeah. Everything went really well, I extended a JPanel to handle the tick/cross display area (tickCross), got the POST code going, strung together the rest of the GUI elements.

The problem was that tickCross.repaint() wasn’t reliably repainting. about 30% of the time the image wouldn’t be painted. The method was being called, but nothing was happening. I tried Google, re-read the related Sun Java docs and was reminded that: “repaint() does not actually paint. It calls the peer repaint which enqueues a request in some platform-dependent way inside the native GUI for a repaint.” – MindProd. Great. My OS was deciding when I was allowed to draw.

Comments (1) | Trackback

Strip /uXXXX From String and Replace it With the Correct Unicode Character

I discovered ‘/uXXXX’ appearing where pretty unicode characters should be within my strings. The strings were to be compared to … other strings, which would have the proper unicode characters, so I had to replace the ‘/uXXXX’ in my strings. I couldn’t find a class to do this, but found enough information to understand what needed to be done. The below function is what I came up with.

Comments (6) | Trackback

Quaqua, OS X Application Bundle – Maven – Netbeans 6.1

To skip the introduction and scroll straight to the tutorial, click here.

[Edit 2009: turns out I couldn't use Java for this program, it's on hold for now. I'll have to rewrite what I've done in ObjC so I can use Apple's libraries. Tutorial below still valid, however.]

I’m currently developing a program to make the lives of people who maintain large RapidWeaver projects easier. As I don’t know Objective C [Edit 2009: that's changed now :)], I am developing this program in Java. Before I started work on this project my only Java GUI development experiences were in Linux, during a University programming paper. The main focus of the paper was “Object Orientated Program Design” – the programs we had to make weren’t supposed to be pretty, merely functional. We used Eclipse – use of “cheat” interface builders like Netbeans would have resulted in a fail grade. I found manually coding the GUI of my programs to be a real chore. I decided to use the new Netbeans 6.1 to create my RapidWeaver helper program for this reason.

I want my program to look as “native Mac OS X” as possible, as the intended end-users will all be working in Mac OS X.

Now that I’ve finally managed to get my program to look like a native OS X program, I thought I’d share the process with the Internet.

To achieve my desired look & feel for both my personal project and the example created for the tutorial I used the following tools:

Netbeans 6.1
Maven Plugin
The OS X Application Bundle Plugin
Quaqua Library

Netbeans 6.1

Netbeans is a multi-language IDE, predominantly used for Java programming. It has a visual form editor which I find intuitive and easy to use.

The code editor is excellent. For the past two years I have been using Eclipse, and have found Netbeans provides many of the same features that I would expect from a mature IDE.

You can learn more about it, and get it from here: Netbeans 6.1.

Maven

The Netbeans Maven Plugin (Mevenide2) is a project management tool. Its features are too many to mention here. You want, no, need this plugin.

It is installed via the Netbeans > Tools > Plugins menu.

The OS X Application Bundle Plugin

This plugin is part of the Mojo Project at Codehaus. To quote the creators, this plugin allows one to: “Package dependencies as an Application Bundle for Mac OS X.”

You can find out more about this Maven plugin here: OS X Application Bundle Plugin.

Quaqua Library

To quote from the Quaqua homepage:

“The Quaqua Look and Feel (Quaqua) is a user interface library for Java applications which wish to closely adhere to the Apple Human Interface Guidelines for Mac OS X.”

You may obtain Quaqua and learn more about it here: Quaqua Library.

All of the above products are of extremely high quality, and provide Java developers with the tools we need to create Mac OS X applications with such convincing appearance and behaviour that they would fool Mr. Jobs himself.

Tutorial

1) Download, install and run Netbeans 6.1.

2) Install the Maven plugin: To do this, select Tools > Plugins from the Netbeans menu. Within the window that opens, select “Available Plugins”. Type “Maven” in the Search box, which should remove the other plugins from the catalogue, leaving you with “Maven” and “Netbeans Maven Hints”. Check the box next to both of these then press “Install”. Follow any instructions that appear.

3) Create a new Netbeans Maven project: Select “File > New Project” from the Netbeans menu. Within the window that appears, select “Maven”. Select “Maven Project”, press “Next”. Select “Maven Quickstart Archetype”, press “Next”. Enter some meaningful information in the fields, then press “Finish”.

You should now have a new Netbeans Maven project. Mine looks like this:

Maven Netbeans Quaqua

4) Setup and configure the Maven “OS X Application Bundle Plugin”: Expand the “Project Files” node and double click on the “pom.xml” file, which opens it for editing. You will need to add the following to your pom.xml file (between the … tags):

          <plugin>
               <groupId>org.codehaus.mojo</groupId>
               <artifactId>osxappbundle-maven-plugin</artifactId>
               <version>1.0-alpha-2-SNAPSHOT</version>
                <executions>
                    <execution>
                        <configuration>
                    <mainClass>com.pagesofinterest.quaqua_maven_netbeans.NewJFrame</mainClass>
                    <bundleName>Quaqua Maven Netbeans</bundleName>
                            <additionalClasspath>
                                <path>/System/Library/Java/</path>
                            </additionalClasspath>
                            <vmOptions>-Dcom.apple.macos.useScreenMenuBar=true</vmOptions>
                </configuration>
                        <phase>package</phase>
                        <goals>
                            <goal>bundle</goal>
                        </goals>
                    </execution>
               </executions>
           </plugin>

If you’ve named any part of your project differently you will need to ensure you make the relevant changes to your pom.xml file.

More information and another usage example may be found here: Simplericity: Making your Java app shine on OS X.

This step is recommended: add a “profiles.xml” file to your project.

Right click on “Project Files” and select “Create profiles.xml”.

Overwrite the file’s contents with:

    <?xml version="1.0" encoding="UTF-8"?>
    <!--
        Project-local overrides to the build process based on detected or user-provided environmental parameters.
    -->
    <profilesXml xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/profiles-1.0.0.xsd">
      <profiles>
        <profile>
          <id>Snapshots</id>
          <repositories>
            <repository>
              <id>Codehaus Snapshots</id>
              <url>http://snapshots.repository.codehaus.org/</url>
              <snapshots>
                <enabled>true</enabled>
              </snapshots>
              <releases>
                <enabled>false</enabled>
              </releases>
           </repository>
         </repositories>
         <pluginRepositories>
           <pluginRepository>
             <id>Codehaus Snapshots</id>
             <url>http://snapshots.repository.codehaus.org/</url>
             <snapshots>
               <enabled>true</enabled>
             </snapshots>
             <releases>
               <enabled>false</enabled>
             </releases>
           </pluginRepository>
         </pluginRepositories>
        </profile>
      </profiles>
      <activeProfiles>
        <activeProfile>Snapshots</activeProfile>
      </activeProfiles>
    </profilesXml>

5) Change project Java version: Right click on the root node of your project (mine, as seen above, is “quaqua_maven_netbeans (jar)) and select “Properties”. In the window that appears, select “Sources”. Here one may change the Java version used for this project. Change it to “1.5” and press “OK”.

6) Create a form for your project: Right click on the root node of your project and select “New > JFrame Form”. Give your new form a name, and make sure it is being added to the correct package. Press “Finish”. Delete the “App.java” file from your project. If you see errors in your new form’s source, open the project’s “Library” node. If one of the files in the library has a red “-” sign in its icon, you haven’t’ downloaded it yet. To do this, right click on the “Libraries” node and select “Download All Libraries”.

Now you should build your project. Right click on the root node and select “Build”. When it has finished, assuming there were no errors, navigate to your project’s directory. Within the “target” folder you should find a .zip, .dmg and .app file. Test out the .app file – it should open with no problems. If it doesn’t, make sure you haven’t missed any part of the above steps.

7) Setup Quaqua: Download the required Quaqua Look & Feel files.

Right click on the “Libraries” node of your project and select “Add Library”. Give the library a GroupID, ArtifactID and Version then press “OK”. Right click on the new library and select “Manually Install Artifact”. Press “Browse” and locate the “quaqua.jar” file, which will be in the “Quaqua/lib” folder that was created when you extracted the Quaqua archive downloaded previously.

In the constructor for the form you created earlier, paste the following:

//Make tabbed panes look like tabbed panes should
        System.setProperty("Quaqua.tabLayoutPolicy","scroll");
        //Move the menu bar to Mac OS X position
           System.setProperty("apple.laf.useScreenMenuBar", "true");
 
        // set the Quaqua Look and Feel in the UIManager
        try {
              UIManager.setLookAndFeel("ch.randelshofer.quaqua.QuaquaLookAndFeel");
        // set UI manager properties here that affect Quaqua
 
         } catch (Exception e) {
             System.out.println("Appropriate error message");
         // take an appropriate action here
         }

More information about Quaqua can be found here: Quaqua Look & Feel.

To give a panel a nice Mac OS titled border, do the following:

Change to the design tab of your form. Add a Panel. Right click on the new panel and select “Customize Code”.

Below the panel’s initialisation line, paste:

Maven Quaqua Netbeans Example

Now we’ll add a tab panel, to prove to ourselves that it really does look native.

To do this simply drag the “Tabbed Pane” from the palette into your JFrame. To add Tabs, drag JPanels into the Tabbed Pane.

Build your project, and run the App file that is generated.

This is what you should see:

Quaqua Maven Netbeans

And that’s it! You’ve successfully installed Netbeans 6.1, installed the Maven plugin, setup Macify and Quaqua!

No you’re ready to start creating the core functionality of your program – good luck!
The example project is available for download here.

Comments (3) | Trackback