Monday, August 27, 2012

Two Solitudes

A thought-provoking presentation re: the dichotomy between software dev and research:

Monday, May 18, 2009

AutoScrolling Flex Form.

At work we have an extensive library for our internal ERP application. A component therein is our Form component. It does a lot of little things such as adding default keyListeners for regularly used form shortcuts, or a getFormValues that loops through all children (and all children of childrenContainers ad infinitum), returning a class that we use for most RemoteObject calls.

Last week I added an autoScroll property to that internal form, using code from Daryl Bantarri's AutoScroll utility class (a class that has a single static method). I had a slight problem with it that required a slight edit or two (breaking the method into a few more manageable functions). (and, of course, my edits had to conform to our internal architectural standards and naming conventions)... so if the "doFunctionName," "canRuleName" or redundant returns in the rule are annoying -- that's my fault --> I wrote a lot of those ridiculous rules over here.

Also, in the comments of Daryl's post, some talked of removing the updateComplete listener. We add a lot of form components dynamically to forms, so listening for anything after an updateDisplayList, etc., is a necessity for our framework. Feel free to get rid of that updateComplete listener if need be, especially if your intended use is to hard-code your components in the form.

A shout out to Patrick who is part owner of Webapper... fellow Northern Coloradan whom I've met a small handful of times at random local tech meetups.


private var _autoScroll : Boolean = false;
public function get autoScroll():Boolean
{
return _autoScroll;
}
public function set autoScroll(value:Boolean):void
{
_autoScroll = value;
if(value)
activateAutoscrollListeners();
}



private function activateAutoscrollListeners():void
{
var container : DisplayObjectContainer = this.parent;
if(container)
{
container.addEventListener(FlexEvent.UPDATE_COMPLETE, doAutoScroll);
container.addEventListener(FocusEvent.FOCUS_IN, doAutoScroll);
}
}


also, on creationComplete (or earlier, since we only need the this.parent in activeAutoScrollLIsteners()):

if(autoScroll)
activateAutoscrollListeners();



private function canAutoScroll(container:Container, focusObject:DisplayObject):Boolean
{
if(!focusObject)
return false;

if(!container)
return false;

if(!container.verticalScrollBar)
return false;

if(!this.contains(focusObject))
return false;

if(focusObject == this)
return false;

return true;
}

/**
* doAutoScroll is the eventListener for the parent container's updateComplete and focusIn. if(canAutoScroll), this method calls
* completeAutoScroll and updates the parent container's verticalScrollPosition.
*
*/
private function doAutoScroll(event:Event):void
{
var container : Container = Container(event.currentTarget);
//Don't want displayObject.Y of event.target. getFocus() is more accurate (i.e., mx.controls.combobox).
var focusObject : DisplayObject = DisplayObject(container.focusManager.getFocus());

if(canAutoScroll(container,focusObject))
{
var itemParent : DisplayObjectContainer = focusObject.parent;
var focusObjectTopY : int = (focusObject.parent == this) ? focusObject.y : addTotalYoffSets(focusObject);
if(container.verticalScrollPosition != focusObjectTopY)
{
completeAutoScroll(container, focusObjectTopY, focusObject);
}
}
}

private function addTotalYoffSets(focusObject:DisplayObject):int
{
var parentContainer : DisplayObjectContainer = focusObject.parent;
var focusObjectTopY : int = focusObject.y ;

while(parentContainer != this.parent) {
focusObjectTopY += parentContainer.y;
parentContainer = parentContainer.parent;
}

return focusObjectTopY;
}

private function completeAutoScroll(container:Container, focusObjectTopY:int, focusObject:DisplayObject):void
{
var focusObjectBottomY : int = focusObjectTopY + focusObject.height;
var lastVisibleY : int = container.height + container.verticalScrollPosition;

if(container.horizontalScrollBar)
lastVisibleY -= container.horizontalScrollBar.height;


if(focusObjectTopY < container.verticalScrollPosition)
{
container.verticalScrollPosition = Math.max( 0, focusObjectTopY - 5 );
}
else if(focusObjectBottomY > lastVisibleY)
{
//scroll down. +5 pixels for good measure.
var newPosition : int = Math.min( container.verticalScrollBar.maxScrollPosition, (container.verticalScrollPosition + (focusObjectBottomY - lastVisibleY)) );
container.verticalScrollPosition = newPosition + 5;
}

}

Monday, May 11, 2009

A Note on SAP / Flex and iPerspective

Ridiculously long time since a post, but, for anyone who knew I went, my trip to Palo Alto wasn't what I had expected. I thought I'd be writing an interface to parse the SAP metadata used to render an SAP screen and render it in a Flex application.

It appears as though it had already been done... not sure if it was/is an open source project, but one thing that did come out of my own experimentation is a little interface called iPerspective.

iPerspective: In the app I was building it seemed to make sense to (instead of manage components' interactivity through states) dispatch a PerspectiveEvent (listened for in the App and pushed back down to all registered components), changing the look of the ApplicationControlBar, and anything else that is a mx.core.container that implements iPerspective.

I'll work with it next week if/when I have time -- if it makes sense in practice, maybe I'll open source it.
Anyway, no real stories. Hope all is well out there.

Saturday, September 13, 2008

a random utility class: ObjectSerializer.

I'm just going through and editing a few old posts. This package (objectSerializer) was one that was needed in the case of a serialized object needing to be passed through a url (yes, we had a case where that was needed).

package of.lovin
{
import flash.utils.ByteArray;

import mx.utils.Base64Decoder;
import mx.utils.Base64Encoder;

public class ObjectSerializer
{

public static function decode(str:String):*
{
// '+' equals '-' and '/' equals '_'

if (str != null)
{

var myPattern : RegExp = new RegExp("-", "g");
var myPattern2 : RegExp = new RegExp("_", "g");
var myPattern3 : RegExp = new RegExp("~", "g");

var urlModifiedString : String = str;
urlModifiedString = urlModifiedString.replace(myPattern,"=");
urlModifiedString = urlModifiedString.replace(myPattern2,"/");
urlModifiedString = urlModifiedString.replace(myPattern3,"\n");


var bytes:ByteArray = new ByteArray();
var bDecoder : Base64Decoder = new Base64Decoder();
bDecoder.decode(urlModifiedString);
bytes = bDecoder.toByteArray() ;

bytes.position = 0;

return bytes.readObject();
}
return null;

}

public static function encode(obj:*):String
{
// '+' equals '-' and '/' equals '_'

var bytes:ByteArray = new ByteArray();
bytes.writeObject( obj );

var bEncoder : Base64Encoder = new Base64Encoder();
bEncoder.encodeBytes(bytes);

var myPattern : RegExp = new RegExp("=", "g");
var myPattern2 : RegExp = new RegExp("/", "g");
var myPattern3 : RegExp = new RegExp('\n', "g");

var urlModifiedString : String = bEncoder.toString();
urlModifiedString = urlModifiedString.replace(myPattern,"-");
urlModifiedString = urlModifiedString.replace(myPattern2,"_");
urlModifiedString = urlModifiedString.replace(myPattern3,"~");

return urlModifiedString ;
}

}
}

Saturday, May 10, 2008

Flex Builder / Eclipse tip du jour.

It's inevitable. You'll be debugging a Flex application, get an error and will need to look at a class, object, function or the like. Instead of scrolling up and down, or digging through directories, do the following:

Ctrl-click on the 'identifier' in question and you're in like Flynn.

30th time is the charm?

Maybe it's a bad idea to start ANOTHER blog that may fall into the same ol' my-last-post-was-five-months-ago pit. But, what the hell...