Mac OS X

A few months ago I stumbled upon what came to be one of the most interesting Swing blogs I’ve ever read. Actually, it is the most interesting Swing blog I know of. Exploding Pixels, by Ken Orr, shows how to create beautiful looking Swing applications for Mac OS X.

Ken has a great sense of design, pays great attention to details and his examples are really well written. Even if you do not work with Mac OS X, you’ll find a lot of valuable information on his blog, in particular how a UI developer should deal with details and pixel-perfect designs. I highly recommend you read all of Ken’s posts right now :)

Sexy Swing Apps on Mac OS X

David Watanabe just decided to release NewsFire free of charge for Mac OS X. NewsFire is my favorite RSS client: simple, clean and good looking.

NewsFire for Free

Following today’s event, Apple just published the announcement of an update to .Mac, their web-based storage and sharing solution. Previously limited to 1 GB of data, including email and WebDAV, .Mac now offers 10 GB of storage.

I am very excited about this announcement as it will make .Mac even more useful to me. I use it to store all my email (IMAP), address book, bookmarks, calendars, some public files (WebDAV) and backup the most important files from my computer. 1 GB was more enough for my email but my files felt a bit cramped.

I always liked .Mac for the IMAP account and the great webmail interface, and it has just gotten better.

.Mac Now With 10GB

Groovy is a very appealing language that I really enjoy using from time to time. Unfortunately, as many other languages, Groovy lacks decent development environments. Even though this shortcoming is being addressed by the Eclipse and IntelliJ, the Groovy Console remains a valuable tool to quickly test an expression or a script.

The console works fine and achieve its purpose really well. However, its GUI is somewhat lacking and integrates badly with Mac OS X. The following screenshot shows what the ordinary Groovy Console looks like on Mac OS X:

Groovy Console on Mac OS X

Mac OS X users will easily spot the problems with this user interface. The menu bar belong to the window rather than to the screen and the shortcuts are wrong (using Ctrl instead of Cmd.) Also, not shown in the screenshot, the About and Quit menu items are not in the appropriate location. After a few tweaks, here is the new UI:

New Groovy Console on Mac OS X

There are three steps required to achieve this kind of integration with Mac OS X, two of them which you are probably already aware of. First, you need to tell Apple’s VM to move the menu bar to the top of screen, out of the application’s frame. At this stage, you also need to give your application its real name, otherwise Mac OS X will use the main class’ fully qualified name (in this case, groovy.ui.Console.) The Groovy code to achieve this is the following:

System.setProperty("apple.laf.useScreenMenuBar", "true")
System.setProperty("com.apple.mrj.application.apple.menu.about.name", "GroovyConsole")
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName())

Make sure to set the properties before you initialize any frame and you will get the desired result. The second part of our “Mac OS Xification” is to use the appropriate shortcut keys in the menus. The java.awt.Toolkit class offers the getMenuShortcutKeyMask() method which returns the system’s default shortcut modifier (Ctrl on Windows and Linux, Cmd on Mac OS X.) Again, using this in your application is quite simple:

def createShortcutWithModifier = { key, modifier -> KeyStroke.getKeyStroke(key,
    Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() | modifier) }
def createShortcut = { key -> createShortcutWithModifier(key, 0) }

// Uses Cmd-Shift-N/Ctrl+Shift+N
def newWindowAction = action(
    name:'New Window', closure: this.&fileNewWindow, mnemonic: 'W',
    accelerator: createShortcutWithModifier(KeyEvent.VK_N, KeyEvent.SHIFT_DOWN_MASK)
)

// Uses Cmd-O/Ctrl+O
def openAction = action(
    name:'Open', closure: this.&fileOpen, mnemonic: 'O',
    accelerator: createShortcut(KeyEvent.VK_O)
)

In this sample code, we just defined Swing actions with correct menu shortcuts. Creating a menu bar with those actions is easy with Groovy’s SwingBuilder. Building the menus is also the opportunity for us to introduce the last trick regarding Mac OS X integration: handling the About and Quit menu items correctly.

def isMac = { System.getProperty("mrj.version") != null }

menuBar {
    menu(text:'File', mnemonic: 'F') {
        menuItem() { action(newFileAction) }
        menuItem() { action(newWindowAction) }
        menuItem() { action(openAction) }
        separator()
        menuItem() { action(saveAction) }
        if (!isMac()) {
            separator()
            menuItem() { action(exitAction) }
        }
    }
    // More menus...
}

This piece of code does not add the exit menu item when the application is running on Mac OS X. Every Mac OS X application shows this menu item in the system controlled menu named after the application itself. This menu appears in bold on the second screenshot. The main problem is to figure out to hook our code to this menu. In my modified version of the Groovy console, here is how I did it:

if (isMac()) {
    ConsoleMacOsSupport.handleMacOs(this.&exit, this.&showAbout)
}

The isMac() could be avoided if ConsoleMacOsSupport was cleverer, but I decided to go with a simple yet effective implementation. As you can see, this class exposes a static method to which you can pass two method references. The methods bound that way will be invoked by the system when the user clicks either the About or Quit menu item in the application’s menu. The support class is also written in Groovy:

package groovy.ui

import com.apple.mrj.*

class ConsoleMacOsSupport implements MRJQuitHandler, MRJAboutHandler {
    static initialized = false
	
    def quitHandler
    def aboutHandler

    public void handleAbout() {
        aboutHandler()
    }

    public void handleQuit() {
        quitHandler()
    }

    public static void handleMacOs(quit, about) {
        if (!initialized) {
            initialized = true
            def handler = new ConsoleMacOsSupport(quitHandler:quit, aboutHandler:about)
            MRJApplicationUtils.registerAboutHandler(handler)
            MRJApplicationUtils.registerQuitHandler(handler)
        }
    }
}

ConsoleMacOsSupport simply delegates two Apple VM’s specific handlers to our Groovy methods. Since Groovy won’t even bother with this class at runtime if it’s not required, it is safe to keep it in the Windows and Linux distribution. This kind of work would usually be achieved through reflection in Java to avoid compile-time headaches.

Groovy makes the use of those handles even sweeter thanks to optional method parameters. For instance, Mac OS X’s quit handler does not expect any argument when invoked. However, we would like to bind the same method to a regular JMenuItem when the application is executed on Linux or Windows. In this case we are actually writing an ActionListener, and a parameter of type EventObject is therefore expected. Groovy is here to make it simple:

// The action's closure (action listener) is bound to the exit(EventObject) method
def exitAction = action(
    name:'Quit', closure: this.&exit, mnemonic: 'Q',
    accelerator: createShortcut(KeyEvent.VK_Q)
)

// The MRJQuitHandler is bound to the exit() method
ConsoleMacOsSupport.handleMacOs(this.&exit, this.&showAbout)

// Optional evt argument
void exit(EventObject evt = null) {
    // Cleanup, etc.
}

Even though I did not used this feature in the Groovy Console, you can also install a handler to hook into Mac OS X’s Preferences menu items. If your application offers some sort of options panel or configuration dialog, make sure to bind it to this menu item because that’s where users expect to find this feature. Last but not least, all those examples work also in pure Java and should not required much work to transpose.

Improving Groovy Console’s GUI

You have probably read about it by now, but Coda is a wonderful new web development environment for Mac OS X. While it is not revolutionary, Coda is a simple yet powerful tool encased in a beautiful user interface. Because it relies on http://Transmit for FTP and SubEthaEdit for code editing (with collaborative support), this editor is a bit more friendly than TextMate or BBEdit.

Coda Project Manager

Coda is not as versatile and extensive as TextMate or BBEdit when it comes to basic text editing, but it offers other features that are real time savers. FTP support is obvious, but the fantastic CSS editor or the web page layout inspector are equally useful. I also really enjoy the inclusion of several books about HTML and CSS, as well as the PHP documentation. I hate web development and anything that can ease the pain is more than welcome.

Coda CSS Editor

Go at least take a look at the screenshot on the official web site. This is a great proof that even boring applications like developer tools can look good and offer nice visual effects. Heck, the web site alone is worth the visit; it’s clean, beautiful and nicely animated.

Panic, the company behind Coda, already conquered me a long time ago with Transmit, their FTP client. I’m happy to say they have found a new customer. TextMate still remains my favorite editor on Mac OS X but I doubt I will ever use it again for PHP/XHTML/CSS development.

This, Is Why I Love Mac OS X

Many people have complained over the years (I know I did) about the lack of support in Swing/AWT for translucent and non-rectangular windows. There are various solutions to that problem. Mac OS X in particular, makes it easy to create translucent windows without calling into native code.

I have often seen that the solution is to set a translucent color on the window’s background, like so:

JFrame f = new JFrame("Translucent?");
f.setBackground(new Color(0.0f, 0.0f, 0.0f, 0.5f));

This works just fine when you want to remove the background altogether and create a non-rectangular shaped window; in which case the last parameter of the Color constructor should be 0.0f. But this piece of code fails miserably when you want to create a translucent window. First, it affects only the background of the window, and not its children. Then, this makes Swing go crazy and creates many repaint problems (damn old setOpaque() issue.)

Apple’s Java implementation offers a clean solution though and here it is:

public static void setWindowAlpha(Window w, float alpha) {
    ComponentPeer peer = w.getPeer();
    if (peer == null) {
        return;
    }
    Class< ? extends ComponentPeer> peerClass = peer.getClass();

    //noinspection EmptyCatchBlock
    try {
        Class< ?> nativeClass = Class.forName("apple.awt.CWindow");
        if (nativeClass.isAssignableFrom(peerClass)) {
            Method setAlpha = nativeClass.getMethod(
                    "setAlpha", float.class);
            setAlpha.invoke(peer, Math.max(0.0f, Math.min(alpha, 1.0f)));
      }
    } catch (ClassNotFoundException e) {
    } catch (NoSuchMethodException e) {
    } catch (IllegalAccessException e) {
    } catch (InvocationTargetException e) {
    }
}

The bits of reflection are there to let this method compile on any OS. Before calling this method though, you must make sure that the window is visible:

JFrame f = new JFrame("Translucent!");
f.setVisible(true);
setWindowAlpha(f, 0.5f);

Even though this method will fail gracefully on Linux and Windows, you probably need/want a more generic solution. You can use the excellent JNA API, a JNI wrapper, for that purpose. Among the examples, you’ll find a class called WindowUtils which contains methods to shape a window and make it translucent.

Unfortunately, the current implementation contains a bug on Mac OS X. They are using the first approach described above. What you need to do is download examples.jar, include it into your project, download the source code of WindowUtils.java and replace the setWindowAlpha() method in the MacWindowUtils inner class by the code above.

Finally, be careful with the method calls order. Windows and Linux require the window to be visible before you can shape it. Mac OS X on the contrary, needs the window to be invisible, at least with JNA’s implementation. Here is an example of how to make a translucent, non-rectangular window that works on all of the aforementioned OSes:

ShapedWindow window = new ShapedWindow();
if (!"Mac OS X".equals(System.getProperty("os.name"))) {
    window.setVisible(true);
}
WindowUtils.setWindowMask(window, createShape());
window.setVisible(true);
WindowUtils.setWindowAlpha(window, 0.5f);

And don’t forget to see how you can use JNA to easily make use of many interesting native libraries.

Translucent Swing Windows on Mac OS X

Today is a great day… I am done with school! I will finally get my M.S. in Computer Science. Today was also the day we finished our final assignment. Our goal was to write some sort of a component-oriented/network-distributed VNC clone. I ended up in charge of the UI that I had to crank out in very little time. Just for fun, here are some pictures from that application.

The following picture shows the mockup I did in Photoshop. Forget about that “Pause” icon, it sucks but I got lazy and didn’t want to find a better one. And yes, I did borrowed everything from various Mac OS X apps (the tabs come from Transmit and the slider from iPhoto.)

SuperVNC

Next, here is a screenshot of the actual application running on Windows XP. Despite the Aqua-like components, the design works pretty well. It took me by surprise.

SuperVNC

My only problem with this UI is that I couldn’t find an easy way to get a unified toolbar, as show in the mockup. While the toolbar looks fine on Windows, it looks a bit weird on Mac OS X, as shown below. The gradient in this picture appears while waiting for the first picture of the remote desktop to be received (or around the said picture if the window is too large.)

SuperVNC

The user interface contains some other niceties. For instance, the toolbar icons turn black, as on Mac OS X, when pressed, pausing a remote connection dims the picture and tabs show cool mouse over/pressed effects.

If you are curious on how I implemented the mockup, I’d be more than happy to share the code with you. The tabs are drawn with a tabbed pane UI delegate, as is the slider. Anyhow, I though it’d be to show that a Swing UI does not have to look like Swing, and that can be achieved very easily.

A Swing User Interface

The Apple Developer Connection just published my article about using Quartz Composer compositions in Dashboard widgets.

The example widget displays Flickr’s most interesting photos of the past 7 days one by one, playing a nice animated transition between each.

Widget

Quartz Composer and Dashboard Widgets

Whenever I have some spare time, I continue my exploration of Cocoa/Objective-C development. Lately, there’s been a few blogs telling the world how vastly superior Cocoa is to Swing. Cocoa is a fine toolkit and some APIs are wonderful but there are things, aside from having to maintain those stupid .h files, that I find quite annoying.

Being used to Java IDEs, it’s hard to forget about refactoring. Xcode does not provide any support for this and because of the way I am used to code now, I am frustrated. But I can live without refactoring.

The real gripe I have against Apple’s developer tools is how the Interface Builder works. It is an impressive, easy to use piece of software that lets you build nice UIs very quickly. You can even do databinding in it, which is very useful. Yet, things are getting hectic with events handling.

In the Interface Builder you can connect an element, for instance a button, to an action in a target. Doing so is easy as you simply have to draw a line connecting the button and the target. When you first build your UI, you generate .h and .m files corresponding to the target (usually called a controller, following the MVC pattern.) In the .m file you find the methods you need to implement to respond to actions in the UI. So far so good.

The real problem arises when you have typed some code in the .m file and want to handle more events. You go back to the Interface Builder, connect another component to an action in a target, and… you’re screwed. You have to explicitly tell Interface Builder to re-generate the target’s .h and .m files. If you do so, you must either replace the files altogether or go through a painful process of merging code. That’s right, you are shown a diff/merge tool and must merge by hand. While it might be acceptable for small applications, like the ones I write to learn Cocoa, I can’t fathom the consequences on large projects. The other solution is not to use Interface Builder to connect actions and do everything in the code.

I am disappointed and I sincerely hope I have missed something big here. If some of you have experience in Cocoa development, please tell me I’m wrong :) I have heard a lot of complains against NetBeans’ GUI Builder for instance, because it generates the UI code rather than putting it into an external file, akin to Interface Builder’s .nib files. I understand those complaints but at least NetBeans GUI Builder, or other Java GUI builders for that matter, let me incrementally work on my UI without worrying about diffing/merging the code.

Cocoa Development Tools

Delicious Monster's Delicious Library is currently available for $20. The catch is there are a limited number of licenses. If you want to experience one of the best applications I have used, here is your chance. Not all of you will need it but if, like me, you own hundreds and hundreds of books (or DVDs, CDs or games) this is really damn useful.

I presented this application a year ago with a bunch of screenshots.

Delicious Library Gambler's Sale

While on the plane I decided to start learning Quartz Composer and this application is even better than I thought at first. As a reminder, Quarte Composer is a developer application you can install on MacOS X 10.4 along with Xcode 2.0. It is located in /Developer/Applications/Graphics Tools. This folder also contains the wonderful Core Image Fun House. So, for those who haven’t see my previous post, here is what Quartz Composer looks like:

#ProgX Image

Quartz Composer lets you create scenes by adding patches and linking them together. Each patch is either an operation or a renderer. You can for instance use the patch Image With String, give it a message by changing it’s String input value, and then link its Image output to a Billboard‘s Image input. That’s it, you got your message on screen.

More than hundred of different patches are available by default and you can mix them to create really impressive scenes. The following picture describes a scene in which you can see a rotating cube. Each face of the cube is textured with an animation. This animation shows a transition between two pictures, the transition being a Core Image ripple. Finally, there is a glowing message in the background.

#ProgX Image

That’s it! In just a few clicks you can create impressive scenes with 3D objects, Core Image filters and animation, Core Audio filters, you can also import pictures from a folder or a Spotlight search, import RSS feeds, etc. At last, your scene can be saved a QTZ document to be seen with Quartz Composer itself or QuickTime 7. You can also export the scene as a QuickTime movie. Finally, you can reuse the scene in your Cocoa application by using the right component.

If you wonder what my example scene looks like, here is a screenshot:

#ProgX Image

See the poor framerate? It means a PowerBook 12″ isn’t good at rendering heavy transitions on 1024×768 while blurring pictures while listening to iTunes :) If you are interested in Quartz Composer, visit the QuartzComps web site, which is a nice place to start at.

Oh and you can also download my stupid scene :)

Quartz Composer, Next

I installed Apple’s Tiger friday and I did not have a lot of time to test it so far. Yet, I found a really cool application shipped with Xcode 2.0, Quartz Composer. You can use it to create scenes with Quartz (hence the name I guess :). In just a few click you can create incredible 3D scenes packed with impressive effects since you can use all the Core Images (and Core Audio) filters. It comes with a few templates you can use to create your own screensavers! Best of all, it looks great and it’s really easy to use:

It really is one of the best applications I have used for a long time. It you have MacOS X 10.4, give it a try, you’ll love it.

I Love Quartz Composer

Sometimes, I stumble upon a nice and lovely application. Delicious Library is one of that kind. Available for MacOS X only, Delicious Library provides an efficient and appealing user interface to take care of your media items. You can use it to catalog and browse your CDs, DVDs, books and video games.

If, like me, you have hundreds of items to put on virtual shelves, Delicious Library will quickly become your best friend. You can either use a webcam or a dedicated scanner to scan barcodes and get items from various Amazon stores automatically. The user interface is really impressive and the authors put a lot of nice details in it. Here are two screenshots that show the extra painting applied to the cover pictures:

As you can see, details like foldings and reflections are draw over the original cover to make the item look like a real one, on a real wooden shelf. You can also zoom in and out to see many items at once:

Delicious Library also let you keep track of borrowers and give you clues to new stuff by getting a list of similar items straight from Amazon:

If you love books or music, it is worth purchasing a license for $40. I also ordered the bluetooth barcode scanner which saved me days of work. It took me only about one hour and a half to add 394 books, 50 games and 60 CDs to Delicious Library. I still have many many books to add though :)

Last but not least, you can export your shelves as a CSV file you can then reuse in other applications. I use it on my french web site to let visitors browse through my entire collection of books.

I wish I had done this application in Java. I had this idea a long time ago but never took the time to actually implement it. Maybe should I enhance my BooksDemo (the one with a 3D rotating book) so that we could use a barcode scanner to get information about books.

Delicious Library