using getDefinitionByName correctly - actionscript-3

here is my code line :
new (getDefinitionByName(String( "mypackage.MyDynamicClass" )) as Class) ;
This generates an error : mypackage.MyDynamicClass is not defined.
I googled and found a solution : Use the name of the class in the import statement.
So,
import mypackage.MyDynamicClass
new (getDefinitionByName(String( "mypackage.MyDynamicClass" )) as Class) ;
It worked!!!
but, I am not satisfied with this solution, as it really violates the benefit of a dynamic class. If i know the name of the class ( in import ), then why i would be using it as a string ?
Any alternatives to make dynamic loading of classes work ?
Vishwas

Take look at this article: http://blogs.adobe.com/cantrell/archives/2010/09/loading-classes-dynamically-in-actionscript-3.html
You cannot avoid including the classes you need at the runtime. You can always use:
import mypackage.*
Be aware at the fact that including all the classes in the package might increase the code size.

It definitely not violating dynamic loading of Class because of our compiler detect unused class/import statement in our project then get rid of those class file for packed as swc or swf so the advantage of our final output file size can reduce.
Unless few times unable reduce file size.
Probably you know what are the class you are trying to load via getDefinitionByName() before make sure that class available in IncludeClass.as
For better way, you can import statement for your project
package
{
public class IncludeClasses
{
import com.abc.db.Database; Database;
import com.abc.RemoteLogTarget; RemoteLogTarget;
import com.abc.LocalLogTarget; LocalLogTarget;
import com.abc.exception.GlobalExceptionHandler; GlobalExceptionHandler;
import com.abc.utils.NetConnectionMonitor; NetConnectionMonitor;
}
}
Stil you want to use your way better you can try with compiler options.

I suggest that you use a abstract factory
http://en.wikipedia.org/wiki/Abstract_factory_pattern
Its a very flexible way to create objects without knowing wich class you are going to instantiate.
Is in this abstract factory class in wich you will need to import all the clases you might create objects from, this will not require you to import all clases in your main class but you will still need to import the abstract factory and the interface to communicate with your new objects.
Here is a quick example:
/*
The interface you will use to communicate with your objects
*/
InterfaceForAllMyClasses.as
public interface InterfaceForAllMyClasses
{
public function callMe();
public function callMe2();
}
/*
Your Classes wich implement the interface
*/
Class1.as
import mypackage.InterfaceForAllMyClasses;
public class Class1 implements InterfaceForAllMyClasses
{
public function callMe() { trace("called Class1"); }
public function callMe2() { trace("called Class1 too"); }
}
Class2.as
import mypackage.InterfaceForAllMyClasses;
public class Class1 implements InterfaceForAllMyClasses
{
public function callMe() { trace("called Class2"); }
public function callMe2() { trace("called Class2 too"); }
}
/*
The Abstract Factory
*/
AbstractFactory.as
import mypackage.InterfaceForAllMyClasses;
public class AbstractFactory
{
public function giveMeObject(classNumber:Number):InterfaceForAllMyClasses
{
switch(classNumber)
{
case 0: return(new Class1()); break;
case 1: return(new Class2()); break;
// for any new class that you add you must add a case entry here
}
}
}
/*
Your Program
*/
import mypackage.InterfaceForAllMyClasses;
import mypackage.AbstractFactory;
MyProgram.as
public class MyProgram
{
var abstractFactory:AbstractFactory = new AbstractFactory();
public function main()
{
var x:InterfaceForAllMyClasses=AbstractFactory.giveMeObject(0);
var y:InterfaceForAllMyClasses=AbstractFactory.giveMeObject(1);
x.callMe();
x.callMe2();
y.callMe();
y.callMe2();
}
}
If you cant import the classes from your main application because they are declared in external modules (swfs), then you can make each module as an Abstract Factory, here is an example:
Interfaces/IModuleInterface.as
package Interfaces
{
public interface IModuleInterface
{
function giveMeObject(classNumber:Number):IObjectInterface;
}
}
Interfaces/IObjectInterface.as
package Interfaces
{
public interface IObjectInterface
{
function callMe():void;
function callMeToo():void;
}
}
Modules/ModuleOne.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Module xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" width="400" height="300" implements="Interfaces.IModuleInterface">
<fx:Script>
<![CDATA[
import Interfaces.IObjectInterface;
public function giveMeObject(classNumber:Number):IObjectInterface
{
switch(classNumber)
{
case 1:
trace("ModuleOne: Instantiating 1");
return(new ModuleOneClassOne());
break;
case 2:
trace("ModuleOne: Instantiating 2");
return(new ModuleOneClassTwo());
break;
}
return(null);
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Label x="10" y="10" text="Module One Loaded"/>
</s:Module>
Modules/ModuleOneClassOne.as
package Modules
{
import Interfaces.IObjectInterface;
public class ModuleOneClassOne implements IObjectInterface
{
public function ModuleOneClassOne()
{
trace("ModuleOneClassOne: Instantiated");
}
public function callMe():void
{
trace("ModuleOneClassOne: called callMe()");
}
public function callMeToo():void
{
trace("ModuleOneClassOne: called callMeToo()");
}
}
}
Modules/ModuleOneClassTwo.as
package Modules
{
import Interfaces.IObjectInterface;
public class ModuleOneClassTwo implements IObjectInterface
{
public function ModuleOneClassTwo()
{
trace("ModuleOneClassTwo: Instantiated");
}
public function callMe():void
{
trace("ModuleOneClassTwo: called callMe()");
}
public function callMeToo():void
{
trace("ModuleOneClassTwo: called callMeToo()");
}
}
}
AbstractFactoryInModules.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="345" height="200">
<fx:Script>
<![CDATA[
import Interfaces.IModuleInterface;
import Interfaces.IObjectInterface;
import mx.events.ModuleEvent;
protected var module:IModuleInterface;
protected var object:IObjectInterface;
protected function ButtonLoadSwf_clickHandler(event:MouseEvent):void
{
loader.unloadModule();
loader.url=moduleUrl.text;
}
protected function loader_readyHandler(event:ModuleEvent):void
{
this.module = (loader.child) as IModuleInterface;
}
protected function ButtonCreateObject_clickHandler(event:MouseEvent):void
{
this.object = this.module.giveMeObject(Number(TClassNumber.text));
}
protected function BCallMe_clickHandler(event:MouseEvent):void
{
this.object.callMe();
}
protected function BCallMeToo_clickHandler(event:MouseEvent):void
{
this.object.callMeToo();
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Button id="ButtonLoadSwf" x="236" y="10" width="99" label="Load SWF"
click="ButtonLoadSwf_clickHandler(event)"/>
<s:Button id="ButtonCreateObject" x="150" y="108" label="Create Object"
click="ButtonCreateObject_clickHandler(event)"/>
<s:TextInput id="TClassNumber" x="96" y="107" width="46" text="1"/>
<s:ModuleLoader x="10" y="39" width="325" height="60" id="loader" ready="loader_readyHandler(event)">
</s:ModuleLoader>
<s:TextInput id="moduleUrl" x="10" y="10" width="218" text="Modules/ModuleOne.swf"/>
<s:Button id="BCallMe" x="96" y="137" width="150" label="callMe"
click="BCallMe_clickHandler(event)"/>
<s:Button id="BCallMeToo" x="96" y="166" width="150" label="callMeToo"
click="BCallMeToo_clickHandler(event)"/>
</s:WindowedApplication>

Related

Code behind for a flex application

I'm working on Flex project and having problems with "connecting" the code-behind to the mxml file (It actually worked before in another project). Both files are in the default package.
Hydw.mxml:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" xmlns="*">
<s:TextArea id="txt_log" x="34" y="171" width="225" height="217"/>
</s:Application>
Hydw.as:
package
{
import flash.events.*;
import flash.external.*;
import flash.media.*;
import mx.controls.TextArea;
import mx.core.*;
import mx.events.*;
import spark.components.*;
public class Hydw extends spark.components.Application
{
public var txt_log:spark.components.TextArea;
public function Hydw ()
{
super();
addEventListener(FlexEvent.CREATION_COMPLETE, this.creationCompleteHandler);
}
private function creationCompleteHandler(param1:FlexEvent) : void
{
WriteToLog("creationCompleteHandler");
}
public function WriteToLog(s:String) : void
{
txt_log.text += s + "\n";
}
I run the application (after releasing) and I see nothing in the TextArea. Why?
By the way, I'm having trouble with the debugging for now, so I can't tell where's the failure exactly.
Obviously it didn't work. There need to make some changes in ActionScript and mxml file.
First: Remove package and class from ActionScript file like:
import mx.events.FlexEvent;
public function creationCompleteHandler(param1:FlexEvent) : void
{
WriteToLog("creationCompleteHandler");
}
public function WriteToLog(s:String) : void
{
txt_log.text += s + "\n";
}
Because It is in default package there isn't required to defined package and class.
Second:
Remove public var txt_log:spark.components.TextArea; from as file. Because it will conflict txt_log with id of textArea in mxml file.
Third:
Remove addEventListener(FlexEvent.CREATION_COMPLETE, this.creationCompleteHandler); from as file and give creation complete event in mxml file. like:
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
creationComplete="creationCompleteHandler(event)">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script source="Hydw.as" />
<s:TextArea id="txt_log" x="34" y="171" width="225" height="217"/>
</s:Application>
And another thing is you forget to include as file inside mxml. like:
<fx:Script source="Hydw.as" />
Hope you understand and help to move forward.
This is what you want
Hydw.mxml
<?xml version="1.0" encoding="utf-8"?>
<abstract:Hydw xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:abstract="test.pack.abstract.*"
minWidth="955" minHeight="600">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:TextArea id="txt_log" x="34" y="171" width="225" height="217"/>
</abstract:Hydw>
and your Hydw.as:
package test.pack.abstract
{
import mx.events.FlexEvent;
import spark.components.Application;
import spark.components.TextArea;
[Bindable]
public class Hydw extends Application
{
public var txt_log:TextArea;
public function Hydw()
{
super();
addEventListener(FlexEvent.CREATION_COMPLETE, init);
}
public function init(evt:FlexEvent):void
{
}
}
}
any visual component used in .mxml code you want to use in .as class
must be declared as public binded variable in your .as class or simply declare your .as class as [Bindable]
That's All

how to work with event in Flex?

import flash.events.Event;
public class RequestEvent extends Event
{
public static const REQUEST:String = "request";
private var Results:Boolean;
public function get Results():Boolean
{
return _Results;
}
public function RequestEvent(Results:Boolean=false)
{
super(REQUEST);
Results = Results;
}
override public function clone():Event
{
return new RequestEvent(Results);
}
}
}
hi can some body explain why we are doing overridding of function clone and calling super(request), new in flex ........so don't mind.
One needs to implement the clone method just so that Flex could re-clone the event in the case when an event handler wishes to dispatch the same event again. Flex does provide a default implementation but one may override the method to clone the event differently, if need be.
As for calling the super method, you must call the super becasue you are extending the Event class. The type (in your case, REQUEST) must be a unique string that would uniquely identify the event to Flex platform.
Hope it helps
Regards.
The question about the overriding of the clone method in custom events is very popular and it seems to be one of the Flex strange things. You can read about it here.
So you have to override this method and only in this method you can define values of custom properties. The method is not usual, so if you try to debug it you will never get the debugger in its body.
If you try to define the value of your custom property in the constructor, the value will be ignorred.
It can be unpractical to use a constant string as the event's type value. In this case all instances of your RequestEvent are of the same type and you could not tell them appart using in different situations. As you can see in the example below, this string is used in action listener to map the listener function.
In this example I have three buttons with different events - normal Event, my version of RequestEvent and your version of it. Have a look at it, I hope it can help to understand the case.
//Application
<fx:Script>
<![CDATA[
import fld02.com.customevent.RequestEvent;
import fld02.com.customevent.RequestEvent2;
import mx.controls.Alert;
private function onCustomGroupBtn2Clicked(evt:RequestEvent):void
{
Alert.show('Btn2Clicked: results = ' + evt.results.toString(), 'This is RequestEvent');
}
private function onCustomGroupBtn3Clicked(evt:RequestEvent2):void
{
Alert.show('Btn3Clicked: Results = ' + evt.Results.toString(), 'This is your RequestEvent');
}
]]>
</fx:Script>
<customevent:CustomGroup
BUTTON1_CLICKED="{Alert.show('Btn1Clicked', 'This is Event')}"
BUTTON2_CLICKED="onCustomGroupBtn2Clicked(event)"
request="onCustomGroupBtn3Clicked(event)"/>
</s:Application>
//CustomGroup
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" width="346" height="144">
<fx:Metadata>
[Event(name="BUTTON1_CLICKED", type="flash.events.Event")]
[Event(name="BUTTON2_CLICKED", type="fld02.com.customevent.RequestEvent")]
[Event(name="request", type="fld02.com.customevent.RequestEvent2")]
</fx:Metadata>
<fx:Script>
<![CDATA[
private function onBtn1Click():void
{
this.dispatchEvent(new Event("BUTTON1_CLICKED"));
}
private function onBtn2Click():void
{
var requestEvent:RequestEvent = new RequestEvent("BUTTON2_CLICKED");
requestEvent.results = true;
this.dispatchEvent(requestEvent);
}
]]>
</fx:Script>
<s:Button x="43" y="31" width="183" label="Generate Event" click="onBtn1Click()"/>
<s:Button x="43" y="62" width="183" label="Generate RequestEvent" click="onBtn2Click()"/>
<s:Button x="43" y="93" width="183" label="Generate Your RequestEvent" click="{this.dispatchEvent(new RequestEvent2(true))}"/>
</s:Group>
//My RequestEvent
package fld02.com.customevent
{
import flash.events.Event;
public class RequestEvent extends Event
{
private var _results:Boolean;
public function RequestEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}
override public function clone():Event
{
var requestEvent:RequestEvent = new RequestEvent(this.type);
requestEvent.results = this.results;
return requestEvent;
}
public function get results():Boolean
{
return _results;
}
public function set results(value:Boolean):void
{
_results = value;
}
}
}
//Your RequestEvent
package fld02.com.customevent
{
import flash.events.Event;
public class RequestEvent2 extends Event
{
public static const REQUEST:String = "request";
public function RequestEvent2(Results:Boolean=false)
{
super(REQUEST);
Results = Results;
}
private var _Results:Boolean;
public function get Results():Boolean
{
return _Results;
}
override public function clone():Event
{
return new RequestEvent2(Results);
}
}
}

Dynamically selecting a static embedded image?

Here's my current situation:
I have images embedded on a class.
package system
{
public class Embedded
{
[Embed(source="assets/srcorangeboxidle.png")]
public static const btnSrcOrangeBoxIdle:Class;
[Embed(source="assets/srcorangeboxpressed.png")]
public static const btnSrcOrangeBoxPressed:Class;
[Embed(source="assets/hl1idle.png")]
public static const btnHL1Idle:Class;
[Embed(source="assets/hl1pressed.png")]
public static const btnHL1Pressed:Class;
public function Embedded(){}
}
}
Now on my main MXML file, I have the following.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Script>
<![CDATA[
import system.Embedded;
protected function toggleButtonState(target:Object,pressed:Boolean=false):void
{
var baseImageName:String = target.id.toString();
if (!pressed) {
target.source = Embedded.[baseImageName+"Idle"];
} else {
target.source = Embedded.[baseImageName+"Pressed"];
}
}
]]>
</fx:Script>
<s:Image id="btnSrcOrangeBox" x="107" y="245" source="{Embedded.btnSrcOrangeBoxIdle}" mouseDown="toggleButtonState(btnSrcOrangeBox,true)" mouseUp="toggleButtonState(btnSrcOrangeBox,false)"/>
<s:Image id="btnHL1" x="107" y="355" source="{Embedded.btnHL1Idle}" mouseDown="toggleButtonState(btnHL1,true)" mouseUp="toggleButtonState(btnHL1,false)"/>
</s:Application>
As you can tell, the above codes don't seem to do the trick. I just want to dynamically select which Embedded.* class to select. Any help or hint will be greatly appreciated.
Remove the dot after the class name. The following should work:
target.source = Embedded[baseImageName + "Idle"];

How to Create Alert Dialog in ActionScript3?

I'm working on a project with Actionscript 3.0 in Flash Pro (CS5). I want to create a confirmation box. If I were using the Flex SDK I could do this using the Alert class in the mx.controls package. However, it seems that no similar control exists in the standard Flash library and any amount of Googling just leads me to Flex references.
Try this Class
package com.whatever {
//Imports
import flash.display.Shape;
import flash.display.Sprite;
import flash.geom.Rectangle;
import flash.events.MouseEvent;
//Class
public class AlertBox extends Sprite {
//Vars
protected var box:Shape;
protected var yesBtn:Sprite;
//Constructor
public function AlertBox($:Rectangle):void {
//Initialise
box = new Shape()
yesBtn = new Sprite()
addChild(box)
addChild(yesBtn)
//Render
with (box.graphics) {
lineStyle(1)
beginFill(0, 0.4)
drawRect($.x, $.y, $.width, $.height)
endFill()
}
with (yesBtn.graphics) {
lineStyle(1, 0x00FF00)
beginFill(0x00FF00, 0.4)
drawRect($.x+$.width-100, $.y$.height-40, 80, 20)
endFill()
}
//Events
yesBtn.addEventListener(MouseEvent.CLICK, yesClickHandler, false, 0, true)
yesBtn.addEventListener(MouseEvent.MOUSE_OVER, yesOverHandler, false, 0, true)
}
//Handlers
protected function yesClickHandler($):void {}
protected function yesOverHandler($):void {}
You said that you can't import mx.Controls in AS3 but the following should work in a flex 4 project:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
creationComplete="init()">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.controls.Alert;
private function init():void
{
Alert.show("This is an Alert!!!");
}// end function
]]>
</fx:Script>
</s:Application>
[UPDATE]
After realizing that I misunderstood the question, I looked on the internet for a Alert component for AS3 projects and found the following:
http://developer.yahoo.com/flash/astra-flash/alertmanager/
I'm going try my hand at creating a replica of the flex framework's Alert control and then update my answer again.
If your final swf is going to run in the browser and have script access, you could just use one of the JavaScript PopUp Boxes:
if(ExternalInterface.available) {
if (ExternalInterface.call("confirm", "Should I trace 'Yes'?")) {
trace("Yes"); // user clicked Okay
} else {
trace("User canceled or the call failed");
}
}
I'm pretty sure this will freeze the Flash UI loop until the JavaScript function returns, so make sure you call it when it's all you want to be doing.
I believe that you can continue to use the same Alert class
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/controls/Alert.html

Drag and Drop in Spark tilelist

I am trying to initiate a drag&drop on a spark tilelist so the user can re-order the list manually.
The problem is : each time i drap and drop, the dropped/dragged entry is duplicated.
My main application is :
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
initialize="initApp()">
<fx:Script source="com/init.as" />
</s:Application>
Included as file is :
import com.Sequence;
import mx.collections.ArrayCollection;
import mx.core.ClassFactory;
import mx.core.FlexGlobals;
import spark.components.List;
import spark.layouts.TileLayout;
public var main:List=new List()
public var ok: ArrayCollection = new ArrayCollection( [
{label:"1-redblue", data:"redblue"},
{label:"2-ncview", data:"ncview"},
{label:"3-greyscale", data:"greyscale"},
{label:"4-alg2", data:"alg2"},
{label:"5-alg", data:"alg"},
{label:"6-occam", data:"occam"},
{label:"7-rainbow", data:"rainbow"},
{label:"8-sst_36", data:"sst_36"},
{label:"9-occam_pastel-30", data:"occam_pastel-30"},
{label:"10-ferret", data:"ferret"}
]);
// ActionScript file
public function initApp(){
var lay:TileLayout=new TileLayout()
var ae:ClassFactory=new ClassFactory(Sequence)
main.layout=lay
main.dataProvider=ok
main.dragEnabled=true
main.dropEnabled=true
main.width=FlexGlobals.topLevelApplication.width
main.height=FlexGlobals.topLevelApplication.height
main.itemRenderer=ae
this.addElement(main);
}
And my item renderer looks like :
package com
{
import mx.controls.TextArea;
import mx.events.FlexEvent;
import spark.components.BorderContainer;
import spark.components.supportClasses.ItemRenderer;
public class Sequence extends ItemRenderer
{
private var borderC:BorderContainer=new BorderContainer()
private var labeli:TextArea=new TextArea()
private var d:Object
public function Sequence()
{
super();
this.addElement(borderC)
this.addEventListener(FlexEvent.CREATION_COMPLETE,doIT)
borderC.width=borderC.height=100
labeli.width=labeli.height=100
borderC.addElement(labeli)
}
override public function set data(d:Object):void{
this.d=d
}
override public function get data():Object{
return d;
}
private function doIT(e:FlexEvent):void{
labeli.text =String(d.label);
}
}
}
The property that allows to drag/drop within the same component (without duplicating) is :
allowDragMove
if set to true, the duplication does not occurs.
#gpasse got me on the right track.
The following fields need to be set to true for a Spark List in Flex 4.6.
dragEnabled="true"
dragMoveEnabled="true"
dropEnabled="true"