Friday, January 18, 2008

Duty Calls. . .

As it turns out, the Process Designer thing I'm building is missing an important feature. That feature is what we in "the biz" call "Save". Its used to take important data that's teetering on the edge of existence, sustained only by the good fortune that electricity has managed to flow constantly through the millions of circuits that compose a stick of RAM - and securely deliver it to a much safer place, like a hard drive, whose promise of data integrity can only be defeated by bumps, magnets, static electricity, liquid, dust, above-normal temperatures or any other condition that will probably happen soon.

So anyway - Nitram's been waiting for me to get this feature finished so that he can use the tool to help him test and exercise the engine. Dragging and dropping sure beats hand-editing XML, right? Fair enough. So, like a good partner, I fired up Photoshop and worked on the UI.

I cut some new graphics for the different node types, tweaked some CSS, and upgraded the look a bit, and added some bells and whistles. I also discovered that my home-brewed method for detecting the center of a Bezier curve wasn't always working. If you remember, I'm adding a button to the middle of each of the connecting lines - well, in some cases, the button was rendering nowhere near the line. So, i had to roll up the sleeves and do this right. I found de Casteljau's algorithm which is perfect for doing just this. I'm not a heavy math guy, but i was able to come up with a cheap implementation in js:


Transition.midpoint = function(e1,cp1,cp2,e2){
var top = [_mp_line(e1,cp1),_mp_line(cp1,cp2),_mp_line(cp2,e2)];
var mid = [_mp_line(top[0],top[1]),_mp_line(top[1],top[2])];
return _mp_line(mid[0],mid[1]);

function _mp_line(p1,p2){
return {
x: (Math.abs(p1.x-p2.x)/2) +Math.min(p1.x,p2.x),
y: (Math.abs(p1.y-p2.y)/2) +Math.min(p1.y,p2.y)}
};
};

All this really does is take the end points and control points that define a curve, and find the midpoints between each adjacent pair. Then it finds the midpoints between each of those midpoints, then again, until there is only one point left. Thats our guy. I think this could've been implemented more slickly using recursion, but i think it would actually make it a longer piece of code. Any way here's the jing of the algorithm, and some of the new UI in action. (Please don't mind the pimpley-looking drag circles and the misplaced text)

In all honesty, I spent a good bit of time today working out the details of the "save" feature. There actually are some interesting challenges in it. Since I've decided not to auto-save or make calls to the server at each event in the gui, There are potentially many changes that will need to be carried out by the time the user saves their work. Within one save request there may be tens of actions to perform, some nodes may get updated, others deleted, others created - some will have new Actions associated with them, some Transitions will be deleted, created, or moved. So, to get ready for this I wrote it out in pseudo-code to make sure that i'll be doing things in the correct order. I'm really almost done, Nitram, I swear. Maybe if I didn't blog so windily, I'd be done with it.

Oh yeah, I had Chix (hippie chicken) patty burgers, sauteed kale and baked beans for dinner whoooooo hoooo!

No comments: