Dynamically selecting a static embedded image? - actionscript-3

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"];

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

Create Custom Dialog Box using dispatch events,states and titlewindow in flex/AS3.0

Since a month Iam working on creating a custom dialog box, having parameters like message,state and modal(true/false)
Eg:
showAlert("Hi, how are you doing","Goodmorning", true);
I have learned how to dispatch event. but unable to dispatch the alertevent/popupManager using States.
Below is the code, I am struggling with.
Main.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
public function onclick(event:MouseEvent):void
{
this.dispatchEvent("Hi, How are you?", "Morning", true);
}
public function dispatchEvent(arg1:String, arg2:String, arg3:Boolean):void
{
var str:*=null;
str.message = arg1;
str.stateName = arg2;
str.modal = arg3;
this.dispatchEvent(new ShowAlert(ShowAlert.SHOW, true));
}
]]>
</mx:Script>
<mx:Button id="click" click="onclick(event)"/>
</mx:Application>
ShowAlert.as
package
{
import flash.events.*;
public class ShowAlert extends Event
{
public var _stateName:String;
public var _closable:Boolean;
public var _message:String;
public var _isModal:Boolean;
public static const SHOW:String="show";
public function flash.events.(arg1:String, arg2:Boolean=false, arg3:Boolean=false)
{
super(arg1, arg2, arg3);
trace("arg1: "+arg1+"\t arg2: "+arg2+"\t arg3: "+arg3);
}
public function set message(arg1:String):void
{
this._message = arg1;
}
public function get message():String
{
return _message;
}
public function get modal():Boolean
{
return _isModal;
}
public function get stateName():String
{
return _stateName;
}
public function set stateName(arg1:String):void
{
this._stateName = arg1;
}
public function set modal(arg1:Boolean):void
{
this._isModal = arg1;
}
public override function clone():flash.events.Event
{
return new ShowAlert(type);
}
}
}
I was unable to write the custom titlewindow using states, so I dint post that.
Please let me know, how to make this happen.
Below is the Sample code, specifying my problem
main.mxml:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
public var info:IModuleInfo;
public var loadalert:DisplayObject;
import mx.modules.ModuleManager;
import mx.modules.IModuleInfo;
import mx.events.ModuleEvent;
public function init():void
{
Alert.show("This is forst alert.");
}
public function Loadalerrt():void
{
trace("loadalertmodule");
info = ModuleManager.getModule("../bin-debug/alerrtmod.swf");
info.addEventListener(ModuleEvent.READY, modEventHandler);
info.load();
}
public function modEventHandler(event:ModuleEvent):void
{
trace("modeventHandler");
loadalert=info.factory.create() as DisplayObject;
can1.addChild(loadalert);
}
]]>
</mx:Script>
<mx:Button label="Alert in Application" id="b1" click="init()" x="29" y="21"/>
<mx:Button label="Load Module" id="b2" click="Loadalerrt();" x="10" y="92"/>
<mx:Canvas id="can1" x="409" y="57" backgroundColor="cyan"/>
</mx:Application>
alerttmod.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="400" height="300">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
public function alertshow():void
{
Alert.show("This is second alert, You Can see it covers whole application, What I want is its scope should be limited to this specific module, not to whole application ");
}
]]>
</mx:Script>
<mx:Button label="Alert in Module" id="b1" click="alertshow()" x="163" y="100"/>
</mx:Module>
Now I see your problem. I think it is not possible to restrict the modal area of the Alert. I can suggest you to fake the modal behaviour by desabling the modules elements while your dialog is being shown.
May be it can help you...
Here are two components to demonstrate it:
//your module with another Alert
<?xml version="1.0" encoding="utf-8"?>
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="400" height="300">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.managers.PopUpManager;
public function alertshow():void
{
Alert.show("This is second alert...");
}
public function alertshow2():void
{
var customAlert:CustomAlert = new CustomAlert();
customAlert.addEventListener("CLOSED", onCustomAlertClosed);
this.enabled = false;
PopUpManager.addPopUp(customAlert, this, false);
PopUpManager.centerPopUp(customAlert);
}
private function onCustomAlertClosed(evt:Event):void
{
this.enabled = true;
}
]]>
</mx:Script>
<mx:Button label="Alert in Module" id="b1" click="alertshow()" x="163" y="100"/>
<mx:Button label="CustomAlert in Module" id="b2" click="alertshow2()" x="163" y="150"/>
<mx:Canvas width="100%" height="100%" backgroundColor="0xbbbbbb" alpha="0.8" visible="{!this.enabled}"/>
</mx:Module>
//simple CustomAlert as a Panel
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="300" height="200">
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
protected function button1_clickHandler(event:MouseEvent):void
{
PopUpManager.removePopUp(this);
this.dispatchEvent(new Event("CLOSED"));
}
]]>
</mx:Script>
<mx:Button x="112" y="128" label="Close" click="button1_clickHandler(event)"/>
</mx:Panel>

using getDefinitionByName correctly

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>

How to detect the click in the middle of a SpinnerList control? With test case and screenshot

How do you detect the click at the item in the middle of a SpinnerList control?
I.e. the typical situation - when user scrolls the SpinnerList, until the needed item is in the middle and after that clicks it?
When I just add a click event handler, then I also wrongly detect the situations, when the user just clicks some item to get it displayed in the middle as shown at this screenshot:
Below is my test case code.
Any suggestions please? I've also tried to use a custom SpinnerListItemRenderer and add a click handler there, but it doesn't change the problem described above.
Main.mxml:
<?xml version="1.0" encoding="utf-8"?>
<s:ViewNavigatorApplication
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
firstView="views.MainHomeView">
</s:ViewNavigatorApplication>
views/MainHomeView.mxml:
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
title="How to detect a click?">
<fx:Script>
<![CDATA[
import mx.collections.ArrayList;
private function handleClick(event:Event):void {
trace('selectedItem: ' + _list.selectedItem);
}
]]>
</fx:Script>
<s:SpinnerListContainer>
<s:SpinnerList id="_list"
click="handleClick(event)"
typicalItem="45"
dataProvider="{new ArrayList([1,5,6,10,15,30])}"
wrapElements="false"/>
</s:SpinnerListContainer>
</s:View>
Solved it myself with a custom itemRenderer -
RedBlack.as:
package {
import flash.events.MouseEvent;
import spark.components.List;
import spark.components.SpinnerList;
import spark.components.SpinnerListItemRenderer;
public class RedBlack extends SpinnerListItemRenderer {
public function RedBlack() {
super();
cacheAsBitmap = true;
minHeight = 50;
setStyle('textAlign', 'center');
addEventListener(MouseEvent.CLICK, handleClick, false, 0, true);
}
override public function set data(value:Object):void {
super.data = value;
setStyle('color', int(value) % 2 ? 'red' : 'black');
}
private function handleClick(e:MouseEvent):void {
var list:SpinnerList = owner as SpinnerList;
var value:int = int(data);
if (list && value == list.selectedItem) {
trace('clicked in the middle: ' + value);
}
}
}
}

changing component properties of SkinnableComponent in Actionscript

Flex 4 separates the visual components into the skins. So how do we access those visual elements from Skinnable component? Here is my code:
<?xml version="1.0" encoding="utf-8"?>
<s:SkinnableComponent xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" skinClass="skins.brushedSkin"
xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Script>
<![CDATA[
import mx.controls.TextInput;
private var txt:String;
public function setText(s:String) {
txt = s;
// the following line doesn't work
var input:TextInput = this.skin.getChildByName("msg") as TextInput;
input.text = s;
}
]]>
</fx:Script>
</s:SkinnableComponent>
I just need to set the text in the TextInput in the brushedSkin skin. But I have no idea how to do this in Flex 4.
First you must specify in your SkinnableComponent the so called Designer-Developer Contract.
Then you should wait for your component to finish its instantiation in order to access its skin parts.
In your particular case you change your code in the following way:
<?xml version="1.0" encoding="utf-8"?>
<s:SkinnableComponent xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" skinClass="skins.brushedSkin"
xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Script>
<![CDATA[
import mx.controls.TextInput;
[SkinPart(required="true")]
public var input:TextInput;
private var txt:String;
public function setText(s:String) {
txt = s;
if (initialized)
input.text = txt;
}
]]>
</fx:Script>
</s:SkinnableComponent>
Then ensure that your skin class contains the following declaration (probably you just need to rename the msg-TextInput to input):
<s:TextInput id="input"/>