Keilly: 2008

Sunday, November 30, 2008

Listen Again v3.4



Update: Widget currently broken due to BBC iPlayer update. Hope to get a fix soon....

Listen to the large archive of recent BBC Radio programmes directly from Dashboard.

Currently supports: Radio 1, 1xtra, Radio 2, Radio 3, Radio 4, 5 live, 5 extra, 6 Music, 7, Asian Network, Radio Scotland, Radio Ulster, Radio Wales

Requires RealPlayer 10.1
Update, RealPlayer 11 doesn't play when Dashboard is hidden. Use RealPlayer 10.1

Download BBCListenAgain Widget

Shortcut Keys:
Space - Play/Pause
Up/Down - Volume
Left/Right - Skip
s - Stop
v - Voiceover feedback
p - Focus on station popup

What's new:
3.4
- Fixed to work with another iPlayer change
- Fixed 'Listen Live'

3.33
- Fixed to work with another iPlayer change
- Added auto update mechanism
- Pressing the 'v' key will enable additional spoken feedback.

3.31
- Descriptions of programmes fixed (broken due to BBC slightly rearranging their iPlayer content)

3.3
- Works with new BBC iPlayer website
- Accessibility: Voiceover use is detected and certain actions are spoken if turned on.
- Better font resizing
- Busy feedback

This has been developed and tested on Mac 10.5

VoiceOver users: when selecting stations use VoiceOver keys with the arrows to select the station from the menu.

Troubleshooting:
Try and play directly from the BBC website. If it works there then it will almost certainly work in Dashboard. If not the problem has historically been issues with RealPlayer - try uninstalling and reinstalling RealPlayer using the version from the BBC website. Reboot after the reinstall to restart Dashboard.

Let me know any other problems.

Mac OS X 10.4 Tiger is required. If you're using Safari, click the download link. When the widget download is complete, Show Dashboard, click the Plus sign to display the Widget Bar and click the widget's icon in the Widget Bar to open it. If you're using a browser other than Safari, click the download link. When the widget download is complete, unarchive it and place it in /Library/Widgets/ in your home folder. Show Dashboard, click the Plus sign to display the Widget Bar and click the widget's icon in the Widget Bar to open it.

Thursday, November 20, 2008

MouseEvents for non-rectangluar components in Swing

Warning: Swing hack ahead!

In Swing component bounds are defined as x,y,width,height, i.e. rectangular.

Also in Swing it's very hard to trap mouse events only for a particular section of a component. Sure we can test in our mouse listener if the location of the event is in a particular section, but this isn't always good enough because the mere act of receiving a mouse event means that the parents of that component never get a crack at processing the event. (See here).

This means that in Swing it is very difficult to simulate non-rectangular components.

Consider the resize grip area in this custom text area:

Although it looks triangular, the grip is actually a (rectangular) component layered in front of the text area. We want the user to be able to grab the grip and drag to resize, but also click in the non-grip area and interact directly with the text field.

This is what we have by default:


This is what we want:


Visually its easy to split into two: make the component non-opaque and paint the corner section with some grip graphics in the paintComponent method - letting the parent show through in the unpainted corner.

However event-wise there's no API to split a component into responsive and non-responsive areas. It would be nice for example if JComponent.processMouseEvent call returned a boolean indicating if the event was actually processed. It doesn't, so we have to hack in a fix.

Luckily Component.getCursor() is continually polled as the mouse cursor moves over a component. Overriding this we can detect where the mouse location is over our grip area and act accordingly.
If it's over the visible grip area we can add a mouse listener and start receiving events, if it's over the transparent area we remove the listener and the events are automatically routed to the parent.

Here's the code for the grip:

public Cursor getCursor(){
PointerInfo info = MouseInfo.getPointerInfo();
Point p = info.getLocation();
SwingUtilities.convertPointFromScreen(p, this);

// Test if in the visible area
if (p.x+p.y > getHeight()){
if (!Arrays.asList(getMouseListeners()).contains(ml))
addMouseListener(ml);

return Cursor.getPredefinedCursor(
Cursor.SE_RESIZE_CURSOR);
}

// In the transparent area, stop listening
if (Arrays.asList(getMouseListeners()).contains(ml))
removeMouseListener(ml);

return super.getCursor();
}

Of course you can make the location test as complex as you like creating components of any shape.

Sunday, September 14, 2008

Word Check iPhone App

A version of the Word Checker App is now available for the iPhone and iPod Touch (Now called "Word Check". Grab it from the iTunes App Store and never have to carry a dictionary for Scrabble, Boggle, crosswords or any other kind of word game.

24-Dec-08 - I can now give out free promo copies of the application. Just email me your email address and I'll send you a code for a free copy. Just promise to leave an honest review (hopefully nice) in the iTunes store - Keilly

08-Oct-08 - A new version of the The Word Checker App has just been released. It sports the following new features:
- Anagram/Bingo Finder
- Crossword Helper
- New everyday English dictionaries.
- Huge Speed Increase.

A whopping 99c from the iTunes App store, or free upgrades for existing users. Search for "Word Check" in the iTunes Store.

  

Saturday, August 30, 2008

Listen Again v3.33



Listen to the large archive of recent BBC Radio programmes directly from Dashboard.

Currently supports: Radio 1, 1xtra, Radio 2, Radio 3, Radio 4, 5 live, 5 extra, 6 Music, 7, Asian Network, Radio Scotland, Radio Ulster, Radio Wales

Requires RealPlayer 10.1
Update, RealPlayer 11 doesn't play when Dashboard is hidden. Use RealPlayer 10.1

Download BBCListenAgain Widget

Shortcut Keys:
Space - Play/Pause
Up/Down - Volume
Left/Right - Skip
s - Stop
v - Voiceover feedback
p - Focus on station popup

What's new:
3.33
- Fixed to work with another iPlayer change
- Added auto update mechanism
- Pressing the 'v' key will enable additional spoken feedback.

3.31
- Descriptions of programmes fixed (broken due to BBC slightly rearranging their iPlayer content)

3.3
- Works with new BBC iPlayer website
- Accessibility: Voiceover use is detected and certain actions are spoken if turned on.
- Better font resizing
- Busy feedback

This has been developed and tested on Mac 10.5

VoiceOver users: when selecting stations use VoiceOver keys with the arrows to select the station from the menu.

Troubleshooting:
Try and play directly from the BBC website. If it works there then it will almost certainly work in Dashboard. If not the problem has historically been issues with RealPlayer - try uninstalling and reinstalling RealPlayer using the version from the BBC website. Reboot after the reinstall to restart Dashboard.

Let me know any other problems.

Mac OS X 10.4 Tiger is required. If you're using Safari, click the download link. When the widget download is complete, Show Dashboard, click the Plus sign to display the Widget Bar and click the widget's icon in the Widget Bar to open it. If you're using a browser other than Safari, click the download link. When the widget download is complete, unarchive it and place it in /Library/Widgets/ in your home folder. Show Dashboard, click the Plus sign to display the Widget Bar and click the widget's icon in the Widget Bar to open it.

Sunday, August 17, 2008

ListenAgain 3.31



Update: It seems the BBC have changed the format of their iPlayer pages again, causing the widget to not be able to play any of the streams. Look out for version 3.32 shortly

An upgrade to BBC ListenAgain. Programmes had started to disappear from the 3.2 version as the BBC moved its ListenAgain archive to its new iPlayer. This version of the widget restores those programmes.

What's new:
3.31
- Descriptions of programmes fixed (broken due to BBC slightly rearranging their iPlayer content)

3.3
- Works with new BBC iPlayer website
- Accessibility: Voiceover use is detected and certain actions are spoken if turned on.
- Better font resizing
- Busy feedback

This has been developed and tested on Mac 10.5

VoiceOver users: when selecting stations use VoiceOver keys with the arrows to select the station from the menu.

Requires RealPlayer 10.1
Update, RealPlayer 11 doesn't play when Dashboard is hidden. Use RealPlayer 10.1

Download BBCListenAgain Widget

For blind users there's also an experimental version that gives extra speech feedback if voice over is turned on.Download VoiceOver Version

Troubleshooting:
Try and play directly from the BBC website. If it works there then it will almost certainly work in Dashboard. If not the problem has historically been issues with RealPlayer - try uninstalling and reinstalling RealPlayer using the version from the BBC website. Reboot after the reinstall to restart Dashboard.

Let me know any other problems.

Mac OS X 10.4 Tiger is required. If you're using Safari, click the download link. When the widget download is complete, Show Dashboard, click the Plus sign to display the Widget Bar and click the widget's icon in the Widget Bar to open it. If you're using a browser other than Safari, click the download link. When the widget download is complete, unarchive it and place it in /Library/Widgets/ in your home folder. Show Dashboard, click the Plus sign to display the Widget Bar and click the widget's icon in the Widget Bar to open it.

Wednesday, July 30, 2008

ListenAgain 3.3


An upgrade to BBC ListenAgain. Programmes had started to disappear from the 3.2 version as the BBC moved its ListenAgain archive to its new iPlayer. This version of the widget restores those programmes.

What's new:

- Works with new BBC iPlayer website
- Accessibility: Voiceover use is detected and certain actions are spoken if turned on.
- Better font resizing
- Busy feedback

This has been developed and tested on Mac 10.5

VoiceOver users: when selecting stations use VoiceOver keys with the arrows to select the station from the menu.

Requires RealPlayer 10.1 Update, RealPlayer 11 doesn't play when Dashboard is hidden. Use RealPlayer 10.1

Download

For blind users there's also an experimental version that gives extra speech feedback if voice over is turned on. Mileage varies from machine to machine Download VoiceOver Version

Troubleshooting:
Try and play directly from the BBC website. If it works there then it will almost certainly work in Dashboard. If not the problem has historically been issues with RealPlayer - try uninstalling and reinstalling RealPlayer using the version from the BBC website. Reboot after the reinstall to restart Dashboard.

Let me know any other problems.

Mac OS X 10.4 Tiger is required. If you're using Safari, click the download link. When the widget download is complete, Show Dashboard, click the Plus sign to display the Widget Bar and click the widget's icon in the Widget Bar to open it. If you're using a browser other than Safari, click the download link. When the widget download is complete, unarchive it and place it in /Library/Widgets/ in your home folder. Show Dashboard, click the Plus sign to display the Widget Bar and click the widget's icon in the Widget Bar to open it.

Wednesday, June 11, 2008

Creating a Swing Dashboard Widget - Summary

So the original intention was to create a Dashboard style widget UI using Swing.

In nine fairly simple steps we've gone from a blue square:



...to a nice looking widget that hopefully looks at home on the modern Desktop:



The only shortcut I took was not to pull out the maths book and write my own transform filter.

I'm very pleased with the result, it was a lot easier than I thought it would be. Hopefully this exercise proves (again) that Swing can be more than just a boring, gray, toolkit suitable for boring, gray, form-filling applications.
The new transparency features especially allow vibrant, modern looking UI's that are relatively simple and quick to create.

So that's really it for the UI.

A few non-UI remarks...

Java widgets have a number of benefits over other widgets systems:
- No framework or widget manager needed
- Platform independent
- Installed from a web-page
- The extensive JDK library available as standard
- Sandboxed and secure automatically
- Familiar language with powerful UI toolkit
- Customizable, fast, accelerated painting (try that in Javascript)

There are still a few non-UI things to do before making this code truly useful: preferences and desktop startup spring immediately to mind.

Performance is also an issue. On my machine the two widgets take about 20 MB of RAM each and 0 CPU cycles when just sitting there. 20MB is considerably more than a simple Widget in Apple's Dashboard for example.
However, in modern machines with RAMs of 1GB+ as standard, and depending who you're asking, maybe this is an increasingly unimportant issue. Especially if the widget is useful.

Feel free to use the Source Code. Don't forget you'll need the filters classes from JHLabs.

Source Code Download

Tuesday, June 10, 2008

Creating a Swing Dashboard Widget - Part 9 (Examples)

So the widget code is beta complete. With some tidying and refactoring it's time to create some simple examples.

Clock Widget Launch
Weather Widget Launch
(Systems other than OSX* require Java 6 update 10)



With the widget specific code pushed into a base class, these two examples just needed code to gather some information and paint themselves: About 100 lines each.

ClockWidget Code:These examples are just a taste of what's possible, rather than meant be really useful as working widgets - e.g. the weather widget is hard coded to San Francisco and could do with some better graphics.
They also illustrate one real advantage over traditional Javascript widgets in the use of the familiar libraries which are shipped as part of the base JDK. The weather reads an Yahoo XML feed and the clock uses a date formatter, both easily done in Java with no external libraries to download, license, ship, or understand.

Source code and summary next.

*I managed to fix the earlier OSX rendering problems by explicitly clearing the graphics before each frame. The widgets will now run on OSX with no additional downloads (Java 1.5).

Wednesday, June 4, 2008

Creating a Swing Dashboard Widget - Part 8 (Close Animation)

To prove that its possible to produce, fairly easily, and faithful interpretation of a UI it's important to get the little touches right.

When I added the close button I mentioned that the close action has a nice swoosh animation as the widget is removed but conveniently didn't implement it.

So I took a shot, and it actually it wasn't too bad.

There's already the basis for it:
- The code that is used in the flipping animation snaps an image of a component and transforms it.
- The marvelous Filter library from JHLabs provides various image distortion filters, or if you want to use no libraries and are good at matrix maths then roll your own BufferedImageOp )

I factored out the general component animation from the flipping animation code to create a simple framework that can visually filter a component over time - just supply the distortion or adjustment.

Using the Image Processing Editor I tried out different filters with different setting. It looks like Dashboard is using a Pinch filter to distort the widget away to nothingness.

The distortion code is quite small: use a pinch filter and gradually adjust the pinch amount and radius over time (once per timerTick()). The same image is painted every few milliseconds, and using this filter it displays the animation.
Oh, and the widget should fade over time too, so gradually reduce the alpha:

Sccchhhuuuupppppppp.....


Webstart the demo (Java 6 update 10 is needed or it'll look funny). Hold 'Alt' to get the close button to appear.

Tuesday, June 3, 2008

Creating a Swing Dashboard Widget - Part 7 (Moving)

Widgets can be moved around by clicking almost anywhere their surface and dragging.
OSX provides this by default when the window decoration is turned off. On Windows a mouse listener has to be attached directly to the widget, and some simple repositioning code added.

With this, and some other tidying up, a demo of progress up till now is possible.

Remember you'll need the Java 6 update 10 for this to work properly. Anything less certainly won't do the transparency and will look poor.

OSX will run it but, as there's no Java 6 update 10 to try, you'll see bad transparency rendering issues (still worth a look though). I still hope the transparency can be fixed without using an additional external library.
Also the font alignment is frustratingly different on different platforms, making the 'Done' and 'i' text buttons look poor on OSX, but this will be fixed [at the cost of writing more code].

Launch Demo

Monday, June 2, 2008

Creating a Swing Dashboard Widget - Part 6 (Flipping)

When the info button is pressed the widget should flip over to reveal the back.
Using a flippable component to hold a blue front and green back, and hooking it up to the info button gives a very nice flipping transition, but with horrifying artifacts on OSX:



Also, on Windows the corners of the widget aren't transparent as expected:



After a little struggling I found that on Windows JPanels were causing the corner painting problem. Although marked as non-opaque their backgrounds were still being cleared to white every repaint! Turning off double buffering by passing false in the JPanel constructor fixed this:



OSX problems remain unresolved for now.

Sunday, June 1, 2008

Creating a Swing Dashboard Widget - Part 5 (Info Button)

Widgets have an info button which when pressed flips the widget over to the back so the user can edit their preferences.

It has a number of visual states:
- usually invisible
- when cursor is over the widget the 'i' fades in.
- when the cursor is over the button a background appears

Changing the state of the button's ButtonModel as the mouse cursor moves over various code is simple. The painting code looks at the model to decide what to paint.
Fading is more tricky, especially as the TimingFramework isn't integrated into the JDK.
So I just used a straight forward Swing Timer that varies the alpha value of the button 'i'. When the state changes the timer is kicked off, and for every timer beat the painting transparency is slightly altered until it's either completely transparent or completely opaque.
It would have been better to use a curve rather than the liner adjustment.


So now I have this:

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

Friday, April 25, 2008

iPass Helper (Beta)

iPass is a great service allowing free connection to pay wifi hotspots around the world.
Unfortunately the iPass client for OSX leaves a lot to be desired:
- Often crashes on startup
- Always crashes on shutdown
- Finding a hotspot is tough - one giant list filtered by city

I can't do much about the first two, but I've written a widget to help with the last.

Install the widget from here.

Enter a search into the text field and the widget will match locations and offer to connect to your pick of results.

Searches can be quite flexible, e.g.:
SFO
Starbucks 18th st
Mission

...and you can search by things that are not visible in iPass directly, e.g. street name.

Preferred country, city, area can be set on the back.

I find it best to start the iPass client before using the widget. The widget uses applescript to select the result in the table, which also has problems, especially for selecting items in large lists which is ridiculously slow. Hence the Beta tag for this widget.

Requires: iPass client and service

This widget is not affiliated with iPass inc.

Mac OS X 10.5 Leopard is required. If you're using Safari, click the download link. When the widget download is complete, Show Dashboard, click the Plus sign to display the Widget Bar and click the widget's icon in the Widget Bar to open it. If you're using a browser other than Safari, click the download link. When the widget download is complete, unarchive it and place it in /Library/Widgets/ in your home folder. Show Dashboard, click the Plus sign to display the Widget Bar and click the widget's icon in the Widget Bar to open it.