Keilly

Thursday, June 28, 2007

Speed up file writing

Simple writing to a file can be achieved by the following:

widget.system("/bin/echo name=" + value + " >> "
+ dataFileName, null);

New lines aren't allowed with this version of the echo command, so only one line can be written at a time. The problem is that system calls aren't very fast: who knows why, perhaps a new shell is created internally each call? Anyway, writing a file of more than a couple of lines is noticeably slow to the user. So we need a way to do this with less system calls.

'printf' does the job perfectly as it allows multiple line writing. Build up the string to write, separating lines with the '\n' character. Then write the whole file in one call....

var dataString = "";
for(i=0; i {
dataString += data[i].name + "=" + data[i].value + "\n";
}
if (dataString.length > 0)
widget.system("/usr/bin/printf '" + dataString +
"' > " + dataFileName, null);

So... much... faster...

Tuesday, June 12, 2007

Safari 3 Public Beta vs Dashcode Public Beta

I just installed the Safari 3 Public Beta, it's very nice but without AdBlock and to a lesser extent Greasemonkey it's never going to replace Firefox. Anyway, after firing up Dashcode Public Beta I noticed that there are rendering problems. Just creating a simple widget and resizing the front design is suddenly very problematic. I suppose Safari 3 has an updated version of Webkit that Dashcode Beta isn't ready for.

Uninstalling Safari 3 fixes things with Dashcode. A bit of a pity as Safari 3 was noticeably quicker that Safari 2 and much much faster than Firefox.

Incidentally, maybe a bonus reason for the release of Safari on Windows is to increase the number of plugins available. Plugins are certainly a big differentiator between Firefox and the other browsers, and while Safari is marginalized only on OSX it won't get the volume of [quality] plugins developed by 'the community' that Firefox does.

ZX Spectrum Widget in WWDC Keynote

While being embarrassed for a room full of grown men enthusiastically cheering and whooping at the announcement of a new 'Finder', I spotted that Steve Jobs was sharing the WWDC 2007 stage with a huge OSX feature that he somehow neglected to mention: My ZX Spectrum widget.
It's on around minute 45, blink very slowly and you'll miss it.

Saturday, June 2, 2007

Use the command line (to read/write files and other fun stuff)

Using the command line from a widget adds the ability to make widgets much more powerful than standard web pages. It's really easy to do by using the widget.system call.

e.g., to run a script (drag the script to your widget 'Files' section):
  widget.system("./myscript.sh", null);
Simple write to file 'data.txt'"
  widget.system("/bin/echo Some data >> data.txt", null);
widget.system("/bin/echo More data >> data.txt", null);
Simple file read from 'data.txt':
  var data =
widget.system("/bin/cat data.txt ", null).outputString;
Run a java application:
  widget.system("/usr/bin/java ", null)
Note the use of the path to the executable in the system call. Looks like the widget doesn't have a good path variable set up in it's shell. Not sure why, but it's easy enough to find an executable location by typing 'which java' in Terminal.

Make sure that the widget has the attribute 'Allow Command Line Access' turned on or instead you'll get a non obvious exception when executing the system call.

Monday, May 28, 2007

Aqua Button Image Templates


Warning, drawing images takes ages!
Bizarrely writing the code for widgets always seems to be the quickest bit, drawing graphics and wrestling with Dashcode sucks up most of the time.

To help with drawing I followed an online guide to creating Aqua buttons and created long and round versions.
Here are the saved template files for Gimp to save all the bother. It's easy to change size, colour and put an icon inside.

(The icons are deliberately rotated above for maximum shock value when viewing the page, hold your laptop sideways for a more realistic view of what to expect)

Round Template
Long Horizontal Template

Sunday, May 27, 2007

Listen Again v2.0


I've just uploaded a new version of the ListenAgain widget. This version adds the much needed, and much requested, ability to skip forward and back through playing programmes. Rather than fast forward the skip jumps ahead in convenient increments.

Funnily enough the thing that took the longest time was drawing the new image for the control buttons.

Requires RealPlayer

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.

Troubleshooting: If you cannot play radio streams, and also cannot play streams directly from the BBC web site in Safari then RealPlayer is probbaly not installed or configured properly.

Friday, May 25, 2007

Resizable Background

The better widgets resize. The apple guidelines here do a nice job of describing how to add the resize corner and code, but to get it to look nice at any size is tricky.

By default Dashcode will create a widget with a nice background image that can have rounded corners, gradient fills, and glass effects. This image does not dynamically resize.

One super simple way to get these effects plus enable resizing is to replace the background image with a canvas, and render draw the background on the fly. It's pretty simple. This code will render a black rounded rectangle at any size...


var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');

context.clearRect(0, 0, canvas.width, canvas.height);

var x = 0;
var y = 0;
var x1 = window.innerWidth - 20;
var y1 = window.innerHeight - 28;
var round = 10; // The roundness of the corners

context.lineJoin = "round";
context.fillStyle = '#000000'; // background color

context.arc(x1-round,y+round, round, -Math.PI/2,
0, 0);
context.arc(x1-round,y1-round, round, 0,
Math.PI/2, 0);
context.arc(x+round,y1-round, round, Math.PI/2,
Math.PI, 0);
context.arc(x+round,y+round, round, Math.PI,
3*Math.PI/2, 0);

context.fill();
The steps to add this to a widget are

- Replace the background image with a canvas
- Size the canvas component to it's largest possible size
- Call size and the rendering code when the widget is shown.

Sizing is canvas is the tricky thing. Dashboard initializes the canvas drawing area to a fixed size when the component is first created - so sizing the canvas later does not increase the available area for drawing - leading to possible clipping. The workaround is to initially size the canvas as large as your widgets maximum size, and to add some code to resize the canvas down to the desired size after creation - but just before the widget is shown (i.e. call it in function show()).

The canvas is quite powerful at drawing, and nice effects can be quickly achieved with its API. This image of an unreleased widget is all drawn on canvases, with some text and and buttons added..


Take a look at the code of the ZX Spectrum widget for a working example of a widget with a resizable canvas