Futurescale, Inc. PureMVC Home

The PureMVC Framework Code at the Speed of Thought


Over 10 years of community discussion and knowledge are maintained here as a read-only archive.

New discussions should be taken up in issues on the appropriate projects at https://github.com/PureMVC

Pages: [1] 2
Print
Author Topic: Fabrication 0.5 released  (Read 11536 times)
Darshan Sawardekar
Sr. Member
****
Posts: 85


View Profile Email
« on: November 11, 2008, 11:29:41 »

Hi All,

I have released Fabrication 0.5. This is mostly a bug fix release but there are a few things that were important to implement for future development. Most important of these is the unit tests. I have implemented unit tests for most of the framework now. And fixed a few various bugs in the process.

[1] : Fabrication Test Runner
[2] : More details on CodeDrunks

peace,
darshan
Logged
Jason MacDonald
Sr. Member
****
Posts: 243


View Profile Email
« Reply #1 on: November 11, 2008, 01:38:41 »

Awesome work Darshan, thank-you very much for all your hard work!
Logged
Jason MacDonald
Sr. Member
****
Posts: 243


View Profile Email
« Reply #2 on: November 11, 2008, 02:29:12 »

Gah, I hate constantly being the bearer of bad news. Fabrication won't compile under FlashCS3. FlashMediator extends FabricationMediator which includes ComponentRouteMapper. This file uses 4 MX Flex only files and thus throws a compile and runtime error.

ComponentRouteMapper.as
:
        import mx.core.ComponentDescriptor;
import mx.core.Container;
import mx.core.UIComponent;
import mx.core.UIComponentDescriptor;
« Last Edit: November 11, 2008, 09:03:47 by jasonmac » Logged
Jason MacDonald
Sr. Member
****
Posts: 243


View Profile Email
« Reply #3 on: November 11, 2008, 09:02:39 »

Looks like the fix isn't too bad. Just need to refactor a bit out of the FabricationMediator into the FlexMediator. It's late so I'll try to post about it in the morning.
Logged
Darshan Sawardekar
Sr. Member
****
Posts: 85


View Profile Email
« Reply #4 on: November 11, 2008, 10:18:47 »

Damn, the hello_flash example is the only one that I didn't recompile! I will move the initializeRouteMapper into the flex mediator.

peace,
darshan
Logged
Darshan Sawardekar
Sr. Member
****
Posts: 85


View Profile Email
« Reply #5 on: November 12, 2008, 12:13:26 »

Hey Jason,

I have fixed this on svn. I will make a minor release later. Before that I want to get some ideas on how best to release Fabrication for flash. I have been doing some research on this and I came across this link,

http://labs.wichers.nu/2007/12/25/using-flex-compiled-code-within-flash/

This seems to indicate that it is possible to compile(not just link) with as3 based swcs with flash by just putting them on the classpath. Is this something you have worked out? Any ideas or suggestion would be great. Thanks.

peace,
darshan
Logged
Jason MacDonald
Sr. Member
****
Posts: 243


View Profile Email
« Reply #6 on: November 12, 2008, 07:13:11 »

I've linked to SWC's, but never tried compiling them into a Flash file. I didn't think it was possible. Reading that article it sounds overly complicated and something most aren't likely to go through just to use a swc.

To be honest I prefer the pure as3 code. I am constantly using the debug tools, in both Flash and Flex, and will almost always take the pure code over a compiled swc in both environments to ensure I can step through all of my code.
« Last Edit: November 12, 2008, 07:19:55 by jasonmac » Logged
Darshan Sawardekar
Sr. Member
****
Posts: 85


View Profile Email
« Reply #7 on: November 12, 2008, 08:35:55 »

I've linked to SWC's, but never tried compiling them into a Flash file. I didn't think it was possible. Reading that article it sounds overly complicated and something most aren't likely to go through just to use a swc.

Jason, what I gathered from the article was that the difficult part may be creating such a swc that works with Flash CS3. The process seemed complicated but with something like ant it's a one time thing to build. After that, the usage was 2 phased, load the library swf and use the classes with the swc on the classpath.

I agree that the swc approach isn't suitable when debugging. But the convenience of a swc surely is useful for general purpose flow. I also go the source route when I encounter something odd, but generally I won't recompile everything from scratch.

Btw, have you used CS4. Is there anything different with its swc implementation.

peace,
darshan
Logged
Jason MacDonald
Sr. Member
****
Posts: 243


View Profile Email
« Reply #8 on: November 12, 2008, 08:42:09 »

Jason, what I gathered from the article was that the difficult part may be creating such a swc that works with Flash CS3. The process seemed complicated but with something like ant it's a one time thing to build. After that, the usage was 2 phased, load the library swf and use the classes with the swc on the classpath.

I'll be honest, I only glanced over the article :( I'll give a full read through when I get a free sec.

Btw, have you used CS4. Is there anything different with its swc implementation.

I haven't used CS4 yet, there isn't a public trial available. I'm hoping that when I go to MAX next week I'll get a copy of a trial to play with. If not, there's "other" methods to get a version to try out. Though I dislike going that route. MY real hope is that they bring back a way to exclude files when compiling. Right now I have to jump through hoops using a JSFL command to compile a "module" swf without classes the parent already loads.
Logged
Darshan Sawardekar
Sr. Member
****
Posts: 85


View Profile Email
« Reply #9 on: November 12, 2008, 08:59:44 »

Me too on the _exclude.xml, very useful feature. Meanwhile, I have pushed a 0.5.1 update with the fix onto googlecode with newer swcs and zip.

peace,
darshan
Logged
Jason MacDonald
Sr. Member
****
Posts: 243


View Profile Email
« Reply #10 on: November 12, 2008, 11:52:18 »

Thanks Darshan.

I've spent the last couple hours trying to figure out why I still couldn't unload my swf. After tons of time running through the debugger, it looks like the issue has to do with swf's using any flash component derived from UIComponent.

UIComponent creates an instance of FocusManager during it's initialization that is listeneing to the Stage, even if you choose to set focusenabed = false AND mouseFocusEnabled = false. It stores this in focusManagers[stage]. Below is the function in UIComponent that creates the instance.

:
/**
         * @private (protected)
         *
         * @langversion 3.0
         * @playerversion Flash 9.0.28.0
*/
protected function createFocusManager():void {
if (focusManagers[stage] == null) {
focusManagers[stage] = new FocusManager(stage);
}
}

FocusManager gives you a means to remove all of its event listeners by calling deactivate() on the FocusManager instance. Calling focusManager.deactivate() on a component will remove the event listeners for focusManagers[this] (this being the component itself) but you have no way to call focusManagers[stage] to deactivate the focusManager that it attached to the stage.

The issue at heart is that focusManagers is a static variable of UIComponent, but it's PRIVATE. You cannot access it by any means other than calling focusManager(), which will only return the focusManager instance associated with that component (button for example) and not the one lingering for stage.

So after removing and cleaning everything up, I still end up with a bunch of listeners attached to the stage from FocusManager that I can't remove. I can't get the actual focusManager instance that contains the stage reference to call deactivate() on it.

So basically you cannot use Flash components in a SWF you intended to load/unload from another SWF.

The strange thing is I've scoured Google and can't find anyone mentioning this problem. I can't believe I'm the first to discover this. But I'm quite sure I'm correct in my findings, unless I'm missing some other way to remove this focusManager instance. I even tested just adding a new UIComponent on the stage with focus disabled and then removing it and I still get the listeners. Without the UIComponent I get no listeners on stage and everything unloads fine  :(
« Last Edit: November 12, 2008, 06:38:48 by jasonmac » Logged
Jason MacDonald
Sr. Member
****
Posts: 243


View Profile Email
« Reply #11 on: November 12, 2008, 12:49:13 »

Well it looks like not all is lost. It seems this is an issue only if the parent SWF does not contain a Flash UIComponent. My guess is that because the owner of the UIComponent class is the child SWF, making the owner of the static var the child SWF also and thus containing a listener to the stage of the parent SWF. If, however, you force the parent SWF to compile with UIComponent in its Class list then when the child creates a UIComponent instance it's the parent who owns the private static reference to stage and not the child. In this case the child removes with out a problem leaving the owner of that static reference in the parent SWF.

Not sure if my explanation makes complete sense, but the end results works. If the loader SWF doesn't contain UIComponent, children using UIComponent will not unload properly. If the parent loader SWF contains UIComponent then child SWF's unload fine.

This goes for Flex too. I had to force my test Flex app to include fl.core.UIComponent in order for it to load/unload Flash SWF's containing UIComponents.
« Last Edit: November 12, 2008, 06:41:14 by jasonmac » Logged
Darshan Sawardekar
Sr. Member
****
Posts: 85


View Profile Email
« Reply #12 on: November 12, 2008, 11:27:13 »

Looking at the FocusManager's constructor it seems to listen for Event.ADDED and Event.REMOVED. You could force it to trigger the internal removeHandler by sending a custom event with stage.dispatchEvent(new Event(Event.REMOVED). That might work but will probably have side effects to existing components. Forcibly linking the component in the parent swf is likely the best approach.

peace,
darshan
Logged
Jason MacDonald
Sr. Member
****
Posts: 243


View Profile Email
« Reply #13 on: November 13, 2008, 05:55:37 »

Looking at the FocusManager's constructor it seems to listen for Event.ADDED and Event.REMOVED. You could force it to trigger the internal removeHandler by sending a custom event with stage.dispatchEvent(new Event(Event.REMOVED). That might work but will probably have side effects to existing components. Forcibly linking the component in the parent swf is likely the best approach.

peace,
darshan

Yeah, I tried that and it seemed to have no effect at all. I couldn't get it to even trigger desipte sending the event from Stage :( It strange that Grant Skinner, someone who is so outspoken about the GC in Flash, would leave such a thing in the components he built for Adobe :(
Logged
Jason MacDonald
Sr. Member
****
Posts: 243


View Profile Email
« Reply #14 on: November 13, 2008, 02:45:13 »

One more small change request, and this is just an order thing. I'm getting errors when trying to unload my that app contains a another core. It seems to be the timing of the controller removal. When you remove the controller of the main app before removing the views (which have sub modules loaded) you end up clearing the commandMap to null. So when the dispose() reaches the child app, if you happen to send a route notification out it finds the commandMap for the parent to be empty despite still being listed as an Observer of routes. Hope that makes sense.

Simply changing the order from

:
public function dispose():void {
sendNotification(FabricationNotification.SHUTDOWN, getApplication());

                        startupCommand = null;

if (controller is IDisposable) {
(controller as IDisposable).dispose();
}

if (view is IDisposable) {
(view as IDisposable).dispose();
}

if (model is IDisposable) {
(model as IDisposable).dispose();
}

singletonInstanceMap.dispose();
singletonInstanceMap = null;

removeCore(multitonKey);
}


to

:
public function dispose():void {
sendNotification(FabricationNotification.SHUTDOWN, getApplication());

startupCommand = null;

if (view is IDisposable) {
(view as IDisposable).dispose();
}

if (model is IDisposable) {
(model as IDisposable).dispose();
}

if (controller is IDisposable) {
(controller as IDisposable).dispose();
}

singletonInstanceMap.dispose();
singletonInstanceMap = null;

removeCore(multitonKey);
}

fixes the issue and lets all the child views unload before killing the main controller.

The other alternative is to check that a command exists. The code chunk below is what is throwing the error from above. The call to commandMap will throw an error if command map is null.

:
/**
* Overrides executeCommand to add the command to the undoStack
* if it is undoable.
*/
override public function executeCommand(note:INotification):void {
var commandList:Array = commandMap[note.getName()];
if (commandList == null) return;

might be better to have it call something like below so it simply returns if the map is null or does not contain the note property.

:

    // check to make sure we have a commandMap  or that the property exists to avoid errors
     if(!commandMap || !commandMap.hasOwnProperty(note.getName())) return;

    var commandList:Array = commandMap[note.getName()];

« Last Edit: November 13, 2008, 02:50:56 by jasonmac » Logged
Pages: [1] 2
Print