Get class by full package name in AS3 - actionscript-3

I have an xml with the following node:
<states package="my.package.states" start="preloader">
<item name="preloader" class="Preloader"/>
<item name="intro" class="Intro"/>
<item name="menu" class="Menu"/>
<item name="level_picker" class="LevelPicker"/>
<item name="credits" class="Credits"/></states>
And now I need to get a class reference to the class with the package attributes on states node plus the class attribute for each item... This is what I tried (among other stuff):
var c:Class = getDefinitionByName('my.package.states.Preloader') as Class;
And no success... Is there a way to get the result I want?

If you want to use getDefinitionByName, the Class needs to be imported.
What you are trying to do there, will not work. MXML is just a markup language, which is "converted" to AS3 by the compiler. What you are trying to do, is like getting into a car and once you have started the engine, you expect the car to change into a motor-cycle, a plane and a refrigerator. This might work in "Transformers", but not in a program.
What you COULD do: inside of our "item"-component, you could create instances of those classes/components and add them to "item".

Related

Iterate through DataContext items without casting it to a viewmodel type

Is their a way to access Items contained in a DataContext without having to explicitly cast it to this ViewModel.
Let's say I'm binding a DataContext on an MvxFrameControl view, then I obtain this DataContext in code-behind once it is binded. It will look like an anonymous object containing a list of Items that are known as the children of this ViewModel. Can I swiss-bind these items, or some properties of this DataContext to another object, and so on?
I.e.
this.DelayBind(() =>
{
var data = DataContext;
// It looks like data contains something called "Items" with a list of children viewModels.
});
Can I access DataContext.Items[0], or at least DataContext.Items, and bind it to an observable collection? Then finally swiss-bind some Items to views (MvxFrameControls) on their DataContext?
So, summary: I'm curious if there is a way to work in code-behind with DataContext and its content so I could create a generic MvxFrameControl that would dispatch the data to custom views based on swiss-binding.
I have ViewModels containing lists of lists, and I want to handle a lot of situations in code-behind as I've experienced a lot of memory problems with MvxListViews containing MvxListViews.
[Edit]
This is actually what I was doing in my code that led me to think I should completely redefine how bindings are done. I'll write a minimal fake axml:
// Warning to anyone: this is a fake layout, don't use that
view_myactivity_layout.axml :
<LinearLayout>
<MvxListView
android:MvxItemTemplate="#layout/food_category_item"
local:MvxBind="ItemsSource FoodCategories" />
</LinearLayout>
food_category_item.axml:
<LinearLayout>
<TextView
local:MvxBind="Text Category" />
<MvxListView
android:MvxItemTemplate="#layout/list_of_food_for_a_category_item"
local:MvxBind="ItemsSource FoodList" />
</LinearLayout>
list_of_food_for_a_category_item.axml:
<LinearLayout>
<TextView
local:MvxBind="Text NameOfThatFood" />
<MvxListView
android:MvxItemTemplate="#layout/list_of_colors_for_that_food_item"
local:MvxBind="ItemsSource FoodList" />
</LinearLayout>
[Etc...]
Nesting binded controls works well, but there are tons of GC happening when scrolling. So that's why I was thinking about making my own binding pattern using reflection for this case.

MVVMCross ValueConverter Parameter

Hello MVVMCross community,
My question is about ValueConverters parameters:
Is there any way to pass a variable to a Value Converter rather than a constant value as a ConverterParameter?
Something like:
<EditText
android:id="#+id/editPrice"
...
local:MvxBind="Text Price; Enabled IsPriceEnabled; BackgroundColor IsPriceEnabled, Converter=Enabled2MvxColor, ConverterParameter=Price"/>
or even pass the whole object for example:
<EditText
android:id="#+id/editPrice"
...
local:MvxBind="Text Price; Enabled IsPriceEnabled; BackgroundColor IsPriceEnabled, Converter=Enabled2MvxColor, ConverterParameter=editPrice"/>
TIA,
When using Windows/XAML IValueConverter you can't really pass data-bound entries into the value converter parameter.
However, using the Tibet binding extensions within MvvmCross, you should be able to do this if you use the form:
local:MvxBind="BackgroundColor Enabled2MvxColor(IsPriceEnabled, Price)"
For more on this - and on whole object binding, see https://github.com/MvvmCross/MvvmCross/wiki/Databinding
I had to do something similar couple of days ago: it's rather convoluted:
<controls:OptionItemControl
ItemTitle="{Binding Path=AccountSettings, Converter={StaticResource ContentItemConverter}, Mode=OneTime,
ConverterParameter=DataRoaming.Text}"
ItemInfo="{Binding Path=AccountSettings, Converter={StaticResource ContentItemConverter}, Mode=OneTime,
ConverterParameter=DataRoaming.Info}"
ItemValue="{Binding AccountSettings.DataRoaming, Mode=TwoWay}"
/>
So my ViewModel has a property AccountSettings, which is a class that has another property DataRoaming, which has several properties like .Text, .Info
I am sure there is much easier way to do what I needed it to do, but I wanted to get from using magic string; I didn't get it at the end, but at-least this makes it easier for me to read and figure out.
so in converter I get the parameter, split it; then from value type and I can navigate through the properties and get the actual value from the class. Of course I could have as well called a method.
Hope this might give you some ideas.

How do I get autocompletion for Flex Metadata?

I took a look at flex metadata and it seems to be quiet straight forward. Though I have a problem, I don't get autocompletion for the metadata.
I'll tell you what I did, maybe you find an error. I want to create my own Style metadata tag named e.g. MyStyle. I want to create my own because it's easier for me to determine at runtime if the metadata was added by me or by the flex framework (therefore I will not use the predefined Style metadata tag).
To add metadata is pretty simple, I just wrote this code to get it work:
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
width="1024" height="768">
<fx:Metadata>
[MyStyle(required="true")]
</fx:Metadata>
</s:Group>
On my WindowedApplication component I added an added to stage listener to the stage. So all elements that are added to the application will fire that Event.ADDED when they are added to the stage. In that eventHandler I scan added elements for my metadata tag.
protected function addedToStageListener(event:Event):void
{
var classInfo:XML = describeType(event.target);
for each (var x:XML in classInfo..metadata)
{
if (x.#name == "MyStyle")
trace(x);
}
}
I also added a flex-config.xml file (in the toplevel of my src folder) to add the compiler options, so that I can read my custom metadata tag on runtime. The file looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<flex-config>
<compiler>
<keep-as3-metadata>
<name>MyStyle</name>
</keep-as3-metadata>
</compiler>
</flex-config>
When I run this, I get the result I expect
<metadata name="MyStyle">
<arg key="required" value="true"/>
</metadata>
So this works. My next step was to add autocompletion when adding the metadata tag to the code. To do this you should create a metadata.xml which specifies the metadata tags right?
So I did this and I ended up with this simple metadata.xml
<?xml version="1.0" encoding="UTF-8"?>
<annotations version="2.1.1">
<metadata name="MyStyle" description="Adds style.">
<context name="class" />
<attribute name="required" type="Boolean" required="true" />
</metadata>
</annotations>
To add the metadata.xml correctly to the project I followed that tutorial by Adobe, but it doesn't work. I don't get autocompletion. Do you have any suggestions?
Update: I use Flash Builder 4.6 Professional and I created a Flex Library Project.

How come you can change the id of an object in Actionscript but still refer to it with its old id?

For instance in Flex 4
?xml version="1.0"?>
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<fx:Script>
<![CDATA[
private function setLabel():void {
trace ("the id is "+myButton.id);
myButton.id = "yourButton";
}
]]>
</fx:Script>
<s:Button id="myButton" label="Click Me" click="setLabel();"/>
the traces when the button is clicked twice are
'the id is myButton' followed by
'the id is yourButton'
Not just an idle query. I was hoping to change the id of custom components when populating a main app with them
I would assume that the id of the when set in mxml is the variable name which also sets the internal id (myButton.id = "myButton") Therefore you're able to change myButton.id to "yourButton" because id and variable name are different properties.
Weird one though I'll admit.
If you were to want to create custom components when populating your main app I would look in to a different approach than laying them all out in mxml. Perhaps creating the components in actionscript and setting them in mxml would be best? ( eg your main class is the mxml app and then you have a class behind that does the heavy lifting of creating the view, with all your custom named components )
Remember that MXML is parsed to ActionScript by mxmlc. mxmlc uses the ID attribute of the mxml tags to map to a public class member at compile time. Changing the runtime value of the ID field would have no change to the class structure.
Example:
<MyComponent>
<Button id="myButton" />
&lt/MyComponent>
When compiled, mxmlc transforms it roughly to:
package {
class MyComponent {
[Bindable]
public var myButton:Button;
// Other junk for class init, etc would show here...
}
}
And is then compiled to SWF byte code. At which point the ID attribute is just an attribute and would have no bearing on the class's functionality. You'd have to actually assign a new Button instance to this.myButton to get it to change.

How to parse an .as (AS3) file

I am looking to get as close as I can to parsing out an AS3 file into objects or XML. For instance, imagine the following class:
package {
class SomeClass extends AnotherClass {
private var someVariable:Number
public function someMethod(someParameter:Number = 4):void {
var someLocalVariable:Number = someParameter * (2 + someVariable);
}
}
}
When parsed, it might be something like:
<package name="">
<class id="783" name="SomeClass" extendsId="782">
<variable id="784" visibility="private" type="Number"/>
<function id="785" name="someMethod" returnType="void">
<parameter id="786" name="someParameter" type="Number">
<expression>
<number value="4"/>
</expression>
</parameter>
<variable id="787" name="someLocalVariable" type="Number"/>
<code>
<assign toId="787">
<expression>
<variable id="786"/>
<operator type="*"/>
<expression>
<number value="2"/>
<operator type="+"/>
<variable id="786"/>
</expression>
</expression>
</assign>
</code>
</function>
</class>
</package>
.. even if I don't get a nice, neat xml structure like this, even if it could just parse AS3 to some kind of capacity, it would be way beyond where I am now.
Any thoughts?
Thanks,
Eric
I have actually ported the PMD parser to AS3.
You can check out http://github.com/teotigraphix/as3parser-framework
Mike
FlexPMD has an as3 parser. (FlexPMD is a Java project by Adobe that does reporting of best practices violations in as3 source code.)
FlexPMD is hosted at http://opensource.adobe.com/wiki/display/flexpmd/FlexPMD
The code is on a subversion repo at http://opensource.adobe.com/svn/opensource/flexpmd/trunk
The down side is you would need to use Maven to build FlexPMD (me, I never managed to get it to work), but since you need just one or three projects, it might be possible to extract those by hand without too much cursing and shouting.
You may also want to wander further into the Flex SDK source code (also on opensource.adobe.com) to see if Adobe provides any other software for parsing as3,but I have not looked there.
There's a lexer, parser, and tokenizer in the AS3eval project:
AS3eval
Take a look at the flash.utils.describeType() documentation.
http://livedocs.adobe.com/flex/gumbo/langref/flash/utils/package.html#describeType()
It's for describe actionscript items at runtime, but should have some use in this case.