ear-fung.us I’m a programmer. I’m also pro-grammar.

17Nov/092

Adobe Air 2.0beta – No more Mac PPC Love

I was a little disappointed this morning when I read in the release notes for the new Adobe AIR 2.0beta version (released today).

adobeairTurns out that they've dropped support for PPC Macs. I'm not sure why they did this, but I'd speculate that it had to do with all the fancy new networking features.

This move is going to alienate a lot of users sill on older PPC hardware. It also makes it so that developers of extremely popular AIR applications (such as TweetDeck) won't want upgrade their apps to utilize these cool new features.

It's easy to upgrade software but extremely hard to upgrade hardware. Perhaps they'll add back PPC support in the final release build, but that's only wishful thinking.

11Jan/09Off

Mileage Tracker

airapp_128Mileage Tracker is an open source AIR application written in Flex. I originally wrote it to help me keep track of tax-deductible mileage. My wife drives all over the area for her business and doesn't write down her mileage (how many of us do?). She does, however keep all her appointments in iCal, along with the address where she went.

This application uses the Google Maps Flash API to determine the distance between two addresses. You can also specify a trip as a "round trip" to calculate the return trip as well.

As with all open source software, you can freely look at the source code and tell me how I could improve it!

This is beta software which means there are probably bugs I haven't found yet. There's also considerable room for improvement and new features. Please let me know in the comments what features you'd like to see in future versions.

Click to read more and comment...

22Oct/088

New Sheetz Air Pumps are Incredibly Awesome

I stopped at a brand new Sheetz near work the other day to fill up the pressure on my tires. To my great surprise, the air pump was completely free, but unlike anything I've ever seen before.

Usually the gas station pumps have that little pressure gauge that pops out of the hose telling you the pressure in a very unreadable sort of way, but this pump was digital. Yes. DIGITAL. And automatic. Yes. AUTOMATIC.

The pump has a LCD screen and arrows that let you adjust the desired pressure that it would fill your tires to. So i set the screen to 43psi and the thing whirred up. I placed the nozzle on my tire valve and waited as the pressure inflated. A few seconds later, the machine beeped. The pressure was correct.

I know its a relatively mundane thing to get excited about, but it was, hand down, the best experience I've ever had filling my tires. Everyone needs to visit a Sheetz to have this experience!

20Sep/080

Air 1.1 Bug

I was working on an application the other day in AIR and discovered a neat little annoying bug that affects Macs (not tested on Windows).

I have two monitors, my main 15" Macbook Pro's built in screen and an external Dell LCD. I usually have my monitors offset since that is how they're physically arranged and I want the mouse to move across the monitors without vertically "jumping" position.

What I found is that on the secondary monitor, an AIR application that contains an HTML dropdown element will display misaligned when the top of the monitors are misaligned in the display configuration. Changing the configuration to align the top of the monitors fixes the problem.

Application dropdown on primary monitor:

Application on secondary monitor with monitor offset like I usually use (see configuration panel behind application):

The application with monitors set to be aligned shows proper functionality of the application:

I have submitted the bug to Adobe.

15Aug/080

AIRLogger – An Adobe AIR Debugging Utility

I've been working in AIR quite a bit lately and have had a need to log certain things to be able to tell exactly what's going in in my application. I thought I'd write a logging class and share it with everyone.

AIRLogger is a quick way to create a log file for debugging an Adobe AIR AJAX application.

All you have to do is include the AIRLogger.js file in your application's window. From there you have access to log anything you want using the command:

log.write("text or variables to be logged");

If the file doesn't already exist, one will be created for you on your desktop called "application.log". Both the location and the file name can be easily changed in the js file. Possible locations could be "desktopDirectory" (default), "applicationDirectory", "applicationStorageDirectory", or a string to the path of your choice. I put it on my desktop for easy access because I'm usually just going to delete the file after I'm done looking at it anyway.

More information and download here.

24Jul/082

script.aculo.us effects in AIR

I'm starting a new Adobe AIR project and was trying to add some snazzy script.aculo.us effects to my application. It worked fine in the preview mode, but when I actually ran the application, I got a sandbox error since AIR is very restrictive on "eval()" statements.

Error: Adobe AIR runtime security violation for JavaScript code
in the application security sandbox (eval)

Turns out that others have had this problem too. script.aculo.us apparently isn't planning on releasing an AIR-compatible version, but I found this great page where a developer re-wrote the code in question.

the offending code in in effects.js at line 254:

    eval('this.render = function(pos){ '+
      'if (this.state=="idle"){this.state="running";'+
      codeForEvent(this.options,'beforeSetup')+
      (this.setup ? 'this.setup();':'')+
      codeForEvent(this.options,'afterSetup')+
      '};if (this.state=="running"){'+
      'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
      'this.position=pos;'+
      codeForEvent(this.options,'beforeUpdate')+
      (this.update ? 'this.update(pos);':'')+
      codeForEvent(this.options,'afterUpdate')+
      '}}');

In order to run this code in an AIR application, it can't be in an eval() statement.
To fix this problem, change that entire code block to:

	/*
	eval('this.render = function(pos){ '+
	'if (this.state=="idle"){this.state="running";'+
	codeForEvent(this.options,'beforeSetup')+
	(this.setup ? 'this.setup();':'')+
	codeForEvent(this.options,'afterSetup')+
	'};if (this.state=="running"){'+
	'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
	'this.position=pos;'+
	codeForEvent(this.options,'beforeUpdate')+
	(this.update ? 'this.update(pos);':'')+
	codeForEvent(this.options,'afterUpdate')+
	'}}');*/
	this.render = function(pos){

		if (this.state=="idle"){
			this.state="running";
			if(this.options["beforeSetupInternal"]) {
			this.options.beforeSetupInternal(this);
			}
			if(this.options["beforeSetup"]) {
				this.options.beforeSetup(this);
		}
		if(this.setup) {
			this.setup();
			}
		if(this.options["afterSetupInternal"]) {
			this.options.afterSetupInternal(this);
			}
		if(this.options["afterSetup"]) {
			this.options.afterSetup(this);
			}
		}
		if (this.state=="running"){
			pos=this.options.transition(pos)*this.fromToDelta+this.options.from;
			this.position=pos;
			if(this.options["beforeUpdateInternal"]) {
				this.options.beforeUpdateInternal(this);
			}
			if(this.options["beforeUpdate"]) {
				this.options.beforeUpdate(this);
			}
			if(this.update) {
				this.update(pos);
			}
			if(this.options["afterUpdateInternal"]) {
				this.options.beforeUpdateInternal(this);
			}
			if(this.options["afterUpdate"]) {
				this.options.beforeUpdate(this);
			}
		}
	}

Thanks King Maxemilian!