Tuesday, March 2, 2010

Mac OSX MySQL installation problem

I recently installed MySQL via homebrew (which I highly recommend). However, when I tried to use the MySQL or MySQLAdmin clients I got an error saying that I couldn't connect to the server through /tmp/mysql.sock. Manually creating the file and running mysqld got me a bit further, but mysqld was failing with another error related to permissions. I finally found an official MySQL bug thread with the solution. Their problem was related to the upgrade installer distributed by MySQL, not with the homebrew install, but I found that the solution worked anyway -- I just needed to run this command (assuming a homebrew installation for the path):
/usr/local/bin/mysql_install_db --rpm
Then I launched mysqld and everything was good to go.

Thursday, August 13, 2009

CFUnited Materials

My CFUnited powerpoint slides are here.

And the application I wrote during my session, along with the necessary helper classes, is here.

Sunday, August 2, 2009

Custom Flex Binding with PropertyChangeEvent

In Flex we have a very powerful tool in the [Bindable] metadata tag. However, it can also be a huge source of inefficiency. Basically, when you mark a property as [Bindable] the compiler adds code that dispatches a generic PropertyChangeEvent typed "propertyChange" when the property changes. Whenever this event is detected, the bindings on your property are evaluated. This is all good and fine until you have a bunch of properties that are all marked as [Bindable]. Now the player is watching for the same event type ("propertyChange") for all your bindings for all your properties. So any time one of them changes the player has to look through all the properties in your class to find the one that actually needs to have its bindings reevaluated. Very inefficient.

Thankfully, the people at Adobe at least gave us a way to work around this CPU deathtrap. You can mark your bindings to evaluate on a custom event type like this: [Bindable('myCustomEventType')]. If you use this wisely then the player will know exactly which property to check out when it detects the event, moving the binding evaluation time back from O(n) to constant time. Much better.

In past projects I've used this method with generic fash.events.Event objects to great success. However, on my current project Jonathan Branam, the lead architect, wanted to be more "correct" and use custom PropertyChangeEvents. Okay, makes sense, should be no problem, right? Well, it was a small problem. So, I set up my custom binding like this:

/**
* The current number of bytes loaded by the server during upload.
*/
protected var _bytesLoaded:int = 0;
[Bindable('bytesLoadedChanged')]
/** @copy #_bytesLoaded **/
public function get bytesLoaded():int{
return _bytesLoaded;
}
public function set bytesLoaded(value:int):void{
if(_bytesLoaded != value){ // only set the value if its different
var oldValue:int = _bytesLoaded;
_bytesLoaded = value;
dispatchEvent(new PropertyChangeEvent('bytesLoadedChanged',
false, false, PropertyChangeEventKind.UPDATE,
_bytesLoaded, oldValue, value, this));
}
}

Then I ran my code and the bindings didn't evaluate. It looked right to me, so what was the problem? I looked at the documentation for PropertyChangeEvent (duh, probably should have been a first step) and found this for the "property" property: "A String, QName, or int specifying the property that changed." So, the "property" property of the PropertyChangeEvent should be the NAME of the property that changed, not a reference to that property (follow that?). That amounted to changing three characters, instead of:

dispatchEvent(new PropertyChangeEvent('bytesLoadedChanged',
false, false, PropertyChangeEventKind.UPDATE,
_bytesLoaded, oldValue, value, this));

I now have:

dispatchEvent(new PropertyChangeEvent('bytesLoadedChanged',
false, false, PropertyChangeEventKind.UPDATE,
'bytesLoaded', oldValue, value, this));

And now my bindings work! For some reason having that property set incorrectly was preventing the player from identifying that I had dispatched a binding event. My guess is that it silently was causing an exception in the PropertyChangeEvent constructor, but I'm not sure. What I do know is that now my bindings work, they're efficient, and they're "correct." And I'm happy.

Wednesday, June 10, 2009

How to make Safari 4 open tabs at startup

I decided to give Safari 4 a try and the inability to set it to open the last set of tabs at start up is driving me crazy. I found a solution that, although not ideal, works well enough to get me by until Chrome comes out for Mac. Its an easy enough solution:

1. Create a new bookmark folder
2. Add the tabs you want to be opened to this folder and order them
3. Goto preferences and set "new windows open with:" to your startup tabs folder

Now when Safari starts it will load those tabs. Unfortunately, these tabs will also load when you open a new window. And if you happen to have a tab open that you wanted to keep and you close the app its gone. You can go to "History->Reopen all windows from last session" in desperate situations. This isn't as nice as just remembering the tabs that were open (like every other modern browser), but its passable.

Tuesday, June 9, 2009

Caching Images to Disk with AIR

In an application I'm currently working on, I create images within the application and want to store them to load later. Because I store the image data in a model object that might be used many places in the running application, I keep the data in memory as a BitmapData object. This turned out to be a problem because you can't write BitmapData objects to disk. Instead you have to write the data to a PNG or JPEG and then save the byte array from that object, and reverse the process to load the data. There may be another way but this is the only solution I could find. Here is my class:

package com.effectiveui.models.widget
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.events.Event;
import flash.utils.ByteArray;
import flash.utils.IDataInput;
import flash.utils.IDataOutput;
import flash.utils.IExternalizable;

import mx.graphics.codec.PNGEncoder;

[RemoteClass(name="com.effectiveui.models.widget.WidgetCategoryDataModel")]
public class WidgetCategoryDataModel implements IExternalizable
{
public var imageData:BitmapData;

protected var loader:Loader;

public function WidgetCategoryDataModel(){
loader = new Loader();
loader.contentLoaderInfo.addEventListener(
Event.COMPLETE, handleBytesLoaded);
}

public function handleBytesLoaded(event:Event):void{
imageData = Bitmap(loader.content).bitmapData;
}

public function writeExternal(out:IDataOutput):void{
var encoder:PNGEncoder = new PNGEncoder();
var bytes:ByteArray = encoder.encode(imageData);
bytes.position = 0; // may not be necessary
out.writeDouble(bytes.length);
out.writeBytes(bytes);
}

public function readExternal(input:IDataInput):void{
var length:Number = input.readDouble();
var pngData:ByteArray = new ByteArray();
input.readBytes(pngData,0,length);

loader.loadBytes(pngData);
}
}
}

You can download the class here.

Traction update

I added some screen shots to the Traction website.

Wednesday, April 8, 2009

Stateful to Stateless Skinning Script

Patrick Hansen has a cool solution for converting stateful skins to stateless.