Thursday, February 28, 2008

ArrayCollection weirdness

I ran into a head-scratcher today...

How can this code:

var index:Number = rows.getItemIndex(partition.placeholderRow );
trace( index + " " + (rows.getItemAt(0) === partition.placeholderRow ) );

give this output?

-1 true

rows is an ArrayCollection with one element. partition.placeholderRow exists and is a valid object. I haven't mucked around with rows.source at all.

Answer follows in comment (so you don't peek ahead and cheat!)

Labels:

Thursday, November 22, 2007

New ObjectHandles Build

I posted a new ObjectHandles build yesterday.  It fixes a couple bugs and integrates some patches people have sent me including:

1) Graphical handle support
2) Fixed aspect ratio support
3) Ability to detect transparency & clicks 

There will likely be another build in the next week to integrate another patch and fix a few a performance issue.

Labels: , ,

Monday, November 19, 2007

XML Facade instead of value objects?

I have a project I'm working on where it'd be great if older versions of the software preserved information in the XML file format that it didn't understand. For example, imagine if Version 1 (V1) of the software had this for a file format:

<data>
<value>1</value>
</data>

Now imagine if V2 of the file added an attribute

<data>
<value type="number">1</value>
</data>

It'd be great if you opened that second file with the V1 software and then saved it again, it would preserve the stuff it didn't understand. Unfortunately that's not how I usually write my value objects. Usually I do something like:


public class ValueObject
{
public var value:Number;
public static function fromXML( xml:XML ) : ValueObject
{
var v:ValueObject = new ValueObject();
v.value = xml.value;
}

public function toXML( ) : XML
{
var xml:XML = <data>;
xml.value = value;
return xml;
}
}


As you can see, anything in the file that it doesn't understand is lost. But what if we followed a facade pattern for our data objects and did something more like this:


public class ValueObject
{
protected var source:XML;

public static function fromXML( xml:XML ) : ValueObject
{
v.source = xml;
}

public function toXML() : XML
{
return source;
}

public function get value() : Number {return source.value;}
public function set value(val:Number) : void {source.value = val;}
}


They both have the exact same API, but the second one will preserve XML attributes (or even nodes) that it doesn't understand.

What about AMF based projects, especially when passing rich objects with a Red5 server? I know there's a pretty seamless mechanism in place if properties aren't known, but how do you get those unknown properties back to the server?

What other solutions or best-practices do other people follow for solving this issue?

Labels: , , ,

Sunday, November 04, 2007

Slow Flex Builder compile and refresh solution - Modules

For the past month I've been plagued with up to three minute compile times on Flex Builder 3 Beta 2. I've also been plagued with long several minute waits of "Refresing bin/".

Last week I solved the issue for one of my projects and prevented it from happening to another.

Apparently embedding graphics causes a performance hit in compiling, refreshing directories, and even just before launching. So if you have a hundred or so of these:

<mx:Button icon="@Embed(...)" />

You'll be in a world of pain. The easiest solution is to move those embed calls into your style sheet and then compile your style sheet as a module.

Here's how to make a style sheet module:

1) Create a new MXML module (file->new->flex->MXML module)
2) Add your stylesheet reference to that.


<?xml version="1.0" encoding="utf-8"?>
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" width="0" height="0"
creationComplete="trace('iconsloaded')">
<mx:Style source="style.css" />
</mx:Module>

3) Next, remove the reference to your style sheet from your main application.
4) Now, in your main MXML or AS file add some code to load your module.

protected var styleLoader:ModuleLoader;
protected function init() : void
{
styleLoader = new ModuleLoader();
styleLoader.addEventListener(ModuleEvent.READY, onModuleLoad );
styleLoader.addEventListener(ModuleEvent.ERROR, onModuleError );
styleLoader.url = "IconsModule.swf";
styleLoader.loadModule();
}
protected function onModuleLoad( e:ModuleEvent ) : void
{
maximize();
var mainApp:MainApplication = new MainApplication();
mainApp.percentHeight = 100;
mainApp.percentWidth = 100;
addChild(mainApp);
}

protected function onModuleError(e : ModuleEvent ) : void
{
Alert.show("Could not load module IconsModule.swf","Error",Alert.OK );
}

You can see there that I intialize my main application component after the module has loaded. I didn't have to do this in a Flex app, but in my AIR app that component wouldn't get all of the new styles if created before the module was loaded.

Option 2

Sometimes, it wasn't practical for me to put the embedded graphic in a stylesheet. In those cases I:

1) Made an interface listing all the embedded graphics

public interface MyGraphicsModule
{
// Bindable tags are there purely to suppress warnings,
// these properties never change after startup.
[Bindable(event="moduleChanged")] function get addIcon() : Class;
...
}

2) Make a class that implements that interface and extends ModuleBase, also embed the graphics in there.

public class MyGraphics extends ModuleBase implements TimeLinerGraphicsModule
{
[Embed(source="/art/toolbars/add.png")]
protected var _addIcon:Class;
public function get addIcon() : Class { return _addIcon; }

...
}
NEVER import or otherwise use this class into your application. The goal is to keep it completely separate.

3) Create a module manager class

public class MyModules
{
[Bindable] public static var graphics:MyGraphicsModule;
}


4) Set MyGraphics to be a module that gets built in your Project->Properties->Flex Modules settings.

5) Load your module somewhere at startup

public function loadModules() : void
{
graphicsModuleLoader = new ModuleLoader();
graphicsModuleLoader.addEventListener(ModuleEvent.READY, onModuleLoaded );
graphicsModuleLoader.addEventListener(ModuleEvent.ERROR, onModuleLoadFailure );
graphicsModuleLoader.url = "MyGraphics.swf";
graphicsModuleLoader.loadModule();
}

protected function onModuleLoaded( event:ModuleEvent ) : void
{
if( event.target == graphicsModuleLoader )
{
var o:Object = event.module.factory.create();
MyModules.graphics = event.module.factory.create() as MyGraphicsModule;
}
}

6) Find the spot in your code that used that icon and replace it

So this:

[Embed(source="/art/icons/addIcon.png")]
public var addIcon:Class;


Would become this:

public var addIcon:Class = MyModules.graphics.addIcon;


This all seems like a pretty tedius job to do, but I ended up writing a perl script to scour the source tree, find all the references, and replace them for me. Unfortunately I did that script as part of my day-job and can't share it with everyone right now. I'll ask for permission on Monday.

The end result was we went from a 3.5 minute wait from saving a code change to executing the application to a 20 second wait. Not too shabby considering the size of the codebase we have.

Labels: ,

Thursday, August 16, 2007

Designer + Developer

Relatively speaking, I'm pretty new to the Flash world. I never slugged through the AS1 days like many of the seasoned warriors out there. I've only worked on a few large Flash projects, and I've generally always worked in the same way.

I had a designer (or designers) who knew flash and were able to create .swfs for me to use. Then I wrote my code (in Eclipse+MTASC) that would load and manipulate those assets they provided. I'd use XRay to figure out how things were structured or named. Occasionally I'd have to remind them to add instance names, or not to name multiple things the same thing, but very rarely would I ever fire up the Flash IDE. Sometimes we'd have a pre-design meeting to talk about things like structure or file naming or whatever, but it was always pretty generic stuff

Lately, I've had two different encounters with other developers who work in a completely different fashion. They take the .fla from the designer, completely rip it apart, and then put it back together in a way that makes sense to them.

Now, I know some designers just aren't capable of making a logical structure for their assets, but some can. In fact, those two encounters I mentioned the designer was the same guy I usually work with and I know he did the same sorts of things I expect from him.

The problem with ripping it apart and putting it back together is now, the next time the designer changes something you need to somehow propagate those changes from the designer's work to your own work. I couldn't imagine I'd ever want to take on the role of managing versions of assets within a file during development, even if that meant the assets weren't made how I would have done them.

So it confuses me when a developer will just automatically start in that style of development no matter what the asset structure looks like. Even if stuff wasn't delivered in a logical manner, I'd want to work with the designer instead of just ripping it apart myself.

Maybe I just haven't been bitten by poor designers like others. Maybe my software engineering background makes me fundamentally think different from the flash developers who come more from a design background. How do you guys prefer to work. Is that different from how you actually end up working?

Oh well.. I guess that's my little rant for the week.

Labels: ,

Thursday, July 05, 2007

SwfControls (Graphical Buttons and Popup Menus)

On Saturday I blogged about a new component I was working on and I got a few responses saying it looked really useful. So I threw up a project page and it's available for download.

I'm calling it "swfControls" for now, but I'm hating the name the more I think of it. Any suggestions? At this point, I'm really considering bundling ALL of my controls together, maybe I should just do that to avoid naming them all.

http://rogue-development.com/swfControls.xml

Right now there's just a binary SWC for download, I'll get full source posted soon.

Enjoy!

Labels: , ,

Sunday, June 10, 2007

Log Viewer & XRay

I've made a bunch of changes to LogViewer, you can get the latest package over at:

http://www.rogue-development.com/logViewer.xml

But much more interestingly, I made the changes in direct response for my desire to improve the logging facilities in XRay.

In case you've never heard of it before, XRay is the best tool for debugging Flash applications out there. It's written by a guy named John Grden that I've had the opportunity to work with for the past year or so. Last week I told him about LogViewer and he added it in to XRay. But it just didn't feel right. It looked clunky and there was some functionality that should be there but was missing. So for the past couple days I've been hacking apart LogViewer, adding in a few features, and making it look a little prettier. Here are the results...



As you can see, the search functionality remains, but with a find-previous option listed.

Two new features include the ability to filter based on a text string, and the ability to highlight lines that contain a text string. Both very useful when you have an application spewing large amounts of logging information at you.

With any Luck, we can get these changes wrapped up over the next week to a release-quality state and post it for all to use.

Labels: , , ,

Thursday, June 07, 2007

ObjectHandle component updated

ObjectHandles, the easy way to add user resizing & movement of objects to your flex application, has been updated.

Changes include:

- Initial rotation support added (still needs some tweaks). Thanks
goes to Alexander Kludt for contribution of most of this feature.
- Metadata for events added. (Thanks Thomas Jakobi!)
- Bug fix for making ObjectHandles dynamically through actionscript
instead of in an MXML document.
- Ability to turn mouse cursor support off (since they are ugly right
now).

A new demo is up and downloads can be found at:
http://www.rogue-development.com/objectHandles.xml
(Clear your browser cache before viewing the demo again, I've seen it
not refresh sometimes, even on a shift-reload on my browser)

Enjoy!

Labels: , ,

AS3 Drawing API oddity

I have a weird bug that I'm having trouble figuring out. I have the following code:

comp.graphics.clear();
comp.graphics.lineStyle(5, 0x888888);
comp.graphics.moveTo(0,0);
comp.graphics.lineTo(0,50);
comp.graphics.lineStyle(0, 0);
comp.graphics.beginFill(0x188888);
comp.graphics.drawCircle(10,10,5);
comp.graphics.endFill();

I would expect that to draw a vertical grey line with a filled in circle to the right of it. What I actually get is this:



It's like flash is drawing my circle and then doing a flood-fill outside the circle instead of inside it like it should. If I remove the call to drawCircle(), I get similar results but without the circle.

My solution was to draw the line and the circle on different objects, but I'm unclear on why this is necessary.

Labels:

Sunday, June 03, 2007

ObjectHandles now has mouse cursor support.

ObjectHandles, the easy way to add user resizing & movement of objects to your flex application, has been updated.

Now, when mousing over the component or the various handles an appropriate mouse cursor will be displayed.

There's been a lot of interest from people about this component. It's seen over 400 downloads and I've received quite a few emails about it. If you interested in following this project more closely, I've set up a google-group where I plan to announce new versions and people can ask questions. To join, go over to:
http://groups.google.com/group/objecthandles

Downloads, examples, etc can be found on the project page:
http://www.rogue-development.com/objectHandles.xml

If the example on the project page seems out of date, you may have to clear your cache. I've found some browsers don't refresh i-frames like they should.

Labels: , ,

Friday, June 01, 2007

Log Viewer

I've started a new project to make a flex component to quickly display largish amounts of text. It's main purpose is to display logging information on screen. It's uses a semi-intelligent algorithm to re-use on screen components and batch UI updates in groups.


http://www.rogue-development.com/logViewer.xml

Labels: , ,

Thursday, May 10, 2007

ObjectHandle updated, and binary now available

I've spent a bit more time on my move/resize flex component and there's now an expanded demo available online.

I've also set up a dump of the latest binary .swc that I've been working on to the website. With any luck this will be of some use to someone.

http://www.rogue-development.com/objectHandles.xml

New in this version:

- Horizontal & Vertical Anchors
- A selection manager

Labels: ,

Monday, May 07, 2007

First look at a Flex Component to resize on screen objects.

I've been spending some time working on a flex component to add "handles" to an on screen object to allow an end-user to resize and move it. It's exactly the same type of functionality when you're using design mode of Flex Builder.

Below is the first look at the current progress I've had.



As you might have noticed it has a few bugs and is far from done feature-wise. It you'd like to keep up on it, take a look at the project page.

If anyone knows of a project doing this same type of functionality, please let me know. I hate to duplicate efforts.

Labels: , ,

Sunday, May 06, 2007

Programatically add constraints through Actionscript

Flex Builder has that great "Constraints" UI that allows you to anchor components to their parent that I'm sure everyone has used.


But what happens if you create an object in actionscript and then you want add constraints to it? There is no "top" property you can set to anchor the component to the top. It turns out the constraint system is entirely based on Flex's style system and can be used as follows:

var someComponent:SomeComponent = new SomeComponent();
var style:CSSStyleDeclaration = new CSSStyleDeclaration();
style.setStyle("top", 0);
style.setStyle("horizontalCenter", 0);
someComponent.styleDeclaration = style;

And BAMN, someComponent will be anchored to the top, center of it's parent (assuming it's parent is a container that supports anchors.) Available style selectors are:

  1. top
  2. left
  3. right
  4. bottom
  5. horizontalCenter
  6. verticalCenter
You could also specify the styles in a css sheet, or by adding them to an already existing style.

Edit...

As a commenter has posted you can also use the setStyle method in addition to the various other methods I mentioned. So the following would also work:

someComponent.setStyle("top",0);

Labels: , ,