Access WindowedApplication from package class - apache-flex

I'm developing an AIR application, where i need to access
WindowedApplication's function from the package class.
This is the Main application (Partial code)
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" creationComplete="initApplication()">
<mx:Script>
<![CDATA[
import mx.events.CloseEvent;
import messages.MessageWindow
public function undock():void {
stage.nativeWindow.visible = true;
stage.nativeWindow.orderToFront();
//Clearing the bitmaps array also clears the applcation icon from the systray
NativeApplication.nativeApplication .icon.bitmaps = [];
}
]]>
</mx:Script>
</mx:WindowedApplication>
Package: (Partial code)
package messages
{
public class MessageWindow extends NativeWindow
{
public function MessageWindow():void
{
stage.addEventListener(MouseEvent.MOUSE_DOWN,onClick);
}
private function onClick(event:MouseEvent):void
{
****** Need to call the undock method from here. *****
}
}
}
Is it possible to call this way or suggest any other solution
Thanks in advance
Senling.

Even if I don't recommend this for the sake of your code design, you can access your method like this:
Application.application.undock()
(if your undock() method is public in the WindowedApplication )

Cant see why it shouldnt work. Go ahead and give it a try, and if any errors come up, post it here.
What you can maybe try is to add parentApplication in front of stage in the MessageWindow method, like this..
parentApplication.stage.addEventListener(MouseEvent.MOUSE_DOWN,onClick);
and then call the undock() method from the onClick() method

Related

How to change/prioritize function execution in flex?

So basically I have a component with my event dispatched:
<components:MyComp id="Id" myDispatchedEvent(event)/>
In script tags I have that function:
private function myDispatchedEvent(event:Event):void
{
//Here I have my static function with title and handler function showConfirmation
Calculate.showConfirmation("String Title", function(event:Close):void
{
if(bla bla bla)
//lots of code etc. ...
});
//myDispatchEvent function continues here..
}
So problem is with my static function's showConfirmation handler, if I go through debug, it just skips that function and continues doing myDispatchedEvent. Why doesn't anonymous function inside showConfirmation function execute?
Thanks
Functions are executing upon call. In your case you have just declaration of it. Call this function somewhere inside Calculate.showConfirmation and it will be executed.
Something like the following:
public class Calculate
{
public static function showConfirmation(title:String, func:Function):void
{
// The call I'm talking about is here
func(new Close());
}
}
Let me say first that what you're trying to do is quite strange. I'd try to code a different solution, but this depends on what you're trying to do. It you tell us a more about it we could find a better way to reach your goal. BTW, you can do something like this:
<?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"
minHeight="600" minWidth="955">
<fx:Script>
<![CDATA[
import mx.events.CloseEvent;
public static function myFunction(param:String, func:Function):void {
trace("executing");
func.apply();
}
protected function labelx_clickHandler(event:MouseEvent):void {
trace("click");
Tests.myFunction("Test", function():void {
if (event.localX > 0) {
trace("Test");
}
else {
trace("No");
}
});
}
]]>
</fx:Script>
<s:Button id="labelx"
label="Click me"
click="labelx_clickHandler(event)"/>
</s:Application>
Something similar what Constantiner has already told you. If you don't execute the function that you're passing to your static function as a parameter inside this static function, it won't be executed.

What undocumented alchemy is necessary to get parentApplication to work

I load an SWF with SWFLoader. Within the loaded .SWF, this.parentApplication is returning NULL. Been searching the internet for eight hours.
code listing as requested:
<?xml version="1.0"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
initialize= "Init();"
visible="false"
>
<mx:Script>
<![CDATA[
import flextrace.Dumper;
private var txt_event:TextEvent = new TextEvent(TextEvent.LINK,false,false,"next.xml");
private var timer:Timer = new Timer(10000);
private function Init():void {
timer.addEventListener(TimerEvent.TIMER,timer_handlr);
timer.start();
}
private function timer_handlr(event:Event) {
Dumper.info("timer_handlr");
if (this.parentApplication == null)
Dumper.info("null");
parentApplication.dispatchEvent(new TextEvent(TextEvent.LINK,false,false,"next.xml"));
}
]]>
</mx:Script>
</mx:Application>
I just was looking through Flex docs and saw an answer on your question, if I understood you correctly:
The parentApplication property of an Application object is never itself; it is either the Application object into which it was loaded, or it is null (for the Application object).
Since, your calling it from the application, it should be null.
Just a quick link for you about accessing nested applications (I haven't tested the solution yet tho, but still, may give you some ideas): Nesting Flex applications - weird issues..
Hope, this would help :)
RYAN GUILL: I tried your suggestion - didn't work. I replaced the dispatchEvent call in the code from the OP with the following: this.dispatchEvent(new TextEvent(TextEvent.LINK,true,false,"next.xml")); Were you saying that this should have triggered the Parent application's event handler for TextEvent.LINK? It didn't work.
Try FlexGlobals.topLevelApplication?
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/core/FlexGlobals.html?filter_flex=4.1&filter_flashplayer=10.1&filter_air=2

Why is my object reference null when trying to reference an mx:Canvas from ActionScript?

this is a follow up question from this one, I don't want to keep going in the comments and preventing people from getting hard-earned reputation... :)
In my Cairngorm command class, to get it to compile I needed to tell it what myCanvas was, so I used this line:
var myCanvas : MyCanvas = new MyCanvas;
I'm guessing that's wrong, though, because although it compiles, if I try to do something like this:
if (myCanvas.subObject.value == 0) { ... }
it'll throw this error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at com.foo.bar.command::MyCommand/execute()
as if the subObject doesn't exist. It looks like I might be getting a new instance of MyCanvas, not the instance I want from the main.mxml with an id of myCanvas. Am I right? How do I fix this?
Edit (10:59pm GMT+1): Okay, so it looks like I've been way too vague here. Here's my main.mxml:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:control="com.foo.bar.control.*"
xmlns:business="com.foo.bar.business.*"
xmlns:view="com.foo.bar.view.*"
applicationComplete="com.foo.bar.util.StartupUtil.init()"
horizontalScrollPolicy="off"
verticalScrollPolicy="off"
borderThickness="0"
paddingBottom="0"
paddingLeft="0"
paddingTop="0"
paddingRight="0"
>
<mx:Script>
<![CDATA[
import com.foo.bar.model.PlayerModelLocator;
[Bindable]
private var model : PlayerModelLocator = PlayerModelLocator.getInstance();
]]>
</mx:Script>
<!-- ========================================================================== -->
<!-- the ServiceLocator where we specify the remote services -->
<business:Services id="services" />
<!-- the FrontController, containing Commands specific to this application -->
<control:PlayerController id="controller" />
<!-- ========================================================================== -->
<mx:Style source="assets/main.css" />
<view:MyCanvas id="myCanvas" />
</mx:Application>
And here's my com/foo/bar/command/MyCommand.as:
package com.foo.bar.command {
/* add to controller
addCommand( MyEvent.EVENT_CHANGE_VOLUME, ChangeVolumeCommand );
*/
import flash.net.SharedObject;
import com.adobe.cairngorm.control.CairngormEvent;
import com.adobe.cairngorm.commands.ICommand;
import com.foo.bar.model.PlayerModelLocator;
import com.foo.bar.event.MyEvent;
import com.foo.bar.view.*;
public class ChangeVolumeCommand implements ICommand {
public function execute(event:CairngormEvent):void {
var model : PlayerModelLocator = PlayerModelLocator.getInstance();
var myEvent : MyEvent = MyEvent(event);
var myCanvas : MyCanvas = new MyCanvas();
var so:SharedObject = SharedObject.getLocal("fixie.video");
if (myCanvas.subObject.value == 0) {
trace("subobject value is 0");
}
}
}
}
Basically, I want to get a handle on the object with ID myCanvas in main.mxml using the myCanvas object in MyCommand.as
Could be a couple of things. First, you need parentheses on your class name after the "new" statement: new MyCanvas(); Second, you may be trying to access your sub component before the component lifecycle is ready for you to do so. (It's hard to tell from the code you posted since there isn't enough context.)
What is the scope of your myCanvas variable? Is it inside a method somewhere? You will need to make it public or give it getter/setter to be able to access it.
You may also be trying to reference it before it has been added to its parent, using the addChild() method.
There really isn't enough code in your examples to determine the problem, but these things should give you somewhere to start looking.
1 way is to add eventListener when your myCanvas will be ready after CreationComplete and to do all your stuff
and the second is:
define your subObject as in myCanvas class so you'll be able to access it on Init Stage of your component.
regards
Eugene
p.s. all of the time everybody want to get answer without well formed sample of their problem, its terrible!!

Event.Complete does not fire when loading a URL

I'm an experienced AS developer, but this is something very basic about flex that I can't figure out. In the class below, I'm not sure why the function imageLoaded would not be executed when the image loads a url. Is there a race condition happening here? The application is completely loaded by the time this object is created and setPicture is called. How can I get the Event.COMPLETE event to fire properly in this case?
The line and Log.info functions are conveniences for me, and they definitely work.
Here's my MXML definition:
<?xml version="1.0" encoding="utf-8"?>
<photo:PhotoClass xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:photo="com.xxx.widgets.photo.*">
<mx:Image id="image"/>
</photo:PhotoClass>
Here's my actionscript:
public class PhotoClass extends Box {
public var image : Image;
public function PhotoClass() {
image = new Image();
image.addEventListener(Event.COMPLETE, imageLoaded);
}
private function line(txt : *) : void {
Log.info(txt, "PhotoClass");
}
public function setPicture(url : String) : void {
line("setPicture: " + url);
image.source = url;
}
public function imageLoaded(event : Event) : void {
line("image loaded");
}
}
eventListeners won't register unless the sprite is attached to the application.
Can you give a reference? Because I believe the issue is something else.
When you declare an mxml file with PhotoClass as its root tag, you're extending the PhotoClass. The <mx:Image> tag in the mxml defines a public variable of type Image in the mxml class; and you already have a public var image:Image; in the super class. This will create a conflict - I'd expect a compile time error.
My guess is that since constructor is called first, it assigns an Image object to the public variable image. When the mxml is executed and the children are created, it assigns a new Image object to the public variable image (instead of correctly throwing an error). Now, the event listener was added to the Image instance created in the constructor, but by the time you set image.source in setProperty, it is a different object altogether. That is why it works when you move the event listener to setPicture - there you're assigning it to the new object.
Change the id of the mxml Image tag to something else and it will work even if the event listener was added from the constructor. Change the name of public var image to something else and you'll get a compile time error in PhotoClass.
Btw, what does the Image tag in the mxml do - is that for showing a different image? In that case you must change its id.
<!-- MyCanvas.mxml -->
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Label id="lbl"/>
</mx:Canvas>
<!-- the main application class -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:local="*"
creationComplete="onCreate()" layout="vertical">
<local:MyCanvas id="canvas1"/>
<mx:Script>
<![CDATA[
public var canvas2:MyCanvas;
public function onCreate():void
{
this.canvas1.lbl.text = "MyCanvas_1";
canvas2 = new MyCanvas();
this.addChild(canvas2);
canvas2.addEventListener(FlexEvent.CREATION_COMPLETE, onCanvas2Created);
}
public function onCanvas2Created(e:FlexEvent):void
{
this.canvas2.lbl.text = "MyCanvas_2";
}
]]>
</mx:Script>
</mx:Application>
I figured it out...
eventListeners won't register unless the sprite is attached to the application. The eventListener in this case was being added in the constructor, before the sprite was added to its parent class. I moved image.addEventListener to setPicture and it worked.

Watching a bindable property

In my flex app I have a public bindable property.
I want it so that every time the value of that property changes, a function gets triggered.
I tried using ChangeWatchers, but it seems those only apply to built-in components like a text box change.
I would like to do that same behavior with a property that changes at runtime.
One option is to use BindingUtils.bindSetter (which incidentally returns a ChangeWatcher):
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="this_creationComplete()">
<mx:Script>
<![CDATA[
import mx.binding.utils.BindingUtils;
import mx.binding.utils.ChangeWatcher;
[Bindable]
public var myValue:int = 0;
private function this_creationComplete():void
{
var cw:ChangeWatcher = BindingUtils.bindSetter(myValueChanged, this, "myValue");
}
private function setValue():void
{
myValue = getTimer();
}
private function myValueChanged(o:Object):void
{
trace("myValue: " + myValue.toString());
// You can also use o.toString() -- the new value will be passed into the function
}
]]>
</mx:Script>
<mx:Button label="Click Me" click="setValue()" />
</mx:Application>
Here, myValueChanged gets called whenever the myValue property changes. There are other ways, of course, but I often use this approach with good results. Hope it helps! Post back with questions and I'll keep an eye out.
Look into BindUtils class as back2dos suggests.
And, also, you can set the name of the event that will be triggered when a change is done to a property (default is propertyChange) like this:
[Bindable("change")]
var myProperty : SomeClass;
That is if ChangeWatchers adds listeners for the change event instead of propertyChange event. Which would be kind of weird, but not impossible with all the mishaps of the flex SDKs.
But again, I think BindUtils class should do the trick for you.
Use the class ObjectProxy or its subclass and wrap up the class that has a property you need to watch. In my example, I'm calling a func if someone is changing the property salary giving it a value of more than 55000 in an object Person:
package com.farata
{
import mx.utils.ObjectProxy;
import flash.utils.*;
use namespace flash_proxy;
public dynamic class MyPersonProxy extends ObjectProxy
{
// The object to wrap up
private var person:Person;
public function MyPersonProxy(item:Person){
super(item);
person=item;
}
flash_proxy override function setProperty(name:*, value:*):void {
if ( name == 'salary'&& value>55000) {
// add a new property to this instance of the
// class Person, which can be used in the calculations
// of the total compensation
setProperty("pension", 0.02);
}
super.setProperty(name, value);
}
}
}
well, the easiest way is to listen to PropertyChangeEvent.PROPERTY_CHANGE ... if you declare a property bindable, then mxmlc generates the code to dispatch this event ... if you let the compiler keep the generated ActionScript, then you'll see it ...
other than that, you might want to have a look at BindingUtils ...

Resources