Keilly: May 2008

Saturday, May 31, 2008

Creating a Swing Dashboard Widget - Part 4 (Close)

Widgets have a close button, it has the following properties:
- Is positioned above the widget just over the top left corner
- It only appears when the user has 'Alt' pressed
- Clicking it causes the widget to close (with a nice swoosh animation)

Well, the animation will have to wait, but the button is easy to knock up in Swing.

- The button will extend AbstractButton and draw it's own close icon of a white cross inside a black disc.
- The button will listen for mouse clicks inside the disc area, and call System.exit(0) to close the widget.
- The widget frame has a JLayeredPane allowing arbitrary placement of the button above the main panel
- Add input/action entries on the widget frame to respond to the alt key and call button.setVisible(true/false).

In the main widget frame class add the button to a high layer, and set up the 'Alt' input actions:

Gives this beauty...

Update: Pressing the 'Alt' key is pretty unintuitive for users to close the widgets. Dashboard has a widget manager which offers an alternate more intuitive method to close them. As the Java widgets are trying to avoid the need for a widget engine, I'll just make the close button fade in and out as the mouse moves in or out of the widget - just like the info button in the next part...

Friday, May 30, 2008

Creating a Swing Dashboard Widget - Part 3 (Transparency)

Now we're talking!

To make the background transparent in Java 6 u10 is simple, just call AWTUtilities.setWindowOpaque(this, false);.

Things for me are more complicated as I'm developing on OSX which doesn't have a u10 build available (Apple are at least a year behind the rest of Java). Luckily OSX has long been able to make Java windows transparent just by setting the window background color a transparent one. Why Sun didn't follow this pattern???

So, to make the JFrame transparent on all platforms:

This gives a distinctly widgetty looking...

OSX is even kinder by allowing this widget to be dragged around, Windows will have to get a special mouse listener later.

Thursday, May 29, 2008

Creating a Swing Dashboard Widget - Part 2 (Border)

Widgets have nice rounded borders. The LineBorder in the JDK doesn't really cut it: It's not anti-aliased, it draws weird artifacts, and it's tough to have the outside of the border transparent while inside the border is opaque.
While there are separate ways to fix these things, it's fairly easy to write one:

As this border does the job of filling the entire background of the component with the component's background color, we can make the actual component transparent and this will leave nice transparent areas outside the curves of the corners. (Opaque components fill their entire bounds with the background color).
The drawback of this is that the border is painted after the component's contents, so custom painting for the widget content must be done in the paint method rather than the paintComponent or it won't show up.

Wednesday, May 28, 2008

Creating a Swing Dashboard Widget

Java 6 u10 will allow transparent windows and undockable applets. This should allow the creation of some Dashboard widget like Swing apps.

I'll see how close I can get to creating a basic widget in Swing. I'll take it one step at the time and post all the code and a demo at the end.

The exercise is purely a UI one. The code marvelousness and resource usage won't be a top concern here.

Step 1 - Test app with basic widget

In this case a blue square that does nothing. In the next few steps I'll try and get it more widget like.

Looks like this:

Saturday, May 24, 2008

Flippable Swing Components

One of the nice things about Dashboard widgets is that their preferences are presented on the reverse of each widget. Doing this means that preferences don't take any extra screen real estate, they don't need a dedicated preferences dialog, and a nice flipping animation gives users a natural sense of their location.

Here's a basic implementation for Java Swing components. Webstart Demo

How it's done
A new ReversibleComponent takes a front and back component and does the following:
The front and back components are placed on top of each other in a JLayeredPane, the back one is initially hidden with setVisible(false).
Pressing the 'i' button starts the transition to the back. The transition animation technique is pretty much the same as my animated tree (why does JRoller delete hosted images after a while??). An image of each of the front and back components is captured, then temporary 'tween' images are composited and displayed in a layer above the real components during the animation.
The animation uses a perspective transform from JHLabs to gradually spin the front image away and the back image in. A semi transparent gradient is also drawn over the top to darken the end of the image spinning 'away' from the user giving a better sense of depth.
Once the animation is complete, the front component is hidden, the back one made visible and the 'tween' image overlay is removed. Voila! A spinning JComponent.

Source Code