views:

3101

answers:

5

Some methods in the Flex API such as CursorManager.setCursor(cursorClass:Class, priority:int = 2, xOffset:Number = 0, yOffset:Number = 0) take a parameter of type Class for a graphic. This example lets you specify a JPG/BMP/SWF as the cursor, but the only way I know to get a Class from an image file is using [Embed] in MXML, and this needs to be done dynamically in AS3 in my case.

There must be a standard solution? Is there a good reason these Flex classes take a Class in the first place?

EDIT: I don't actually care about emulating the [Embed] tag's behaviour. I just want to be able to use an image file path with CursorManager. I'm sure I've seen this done in other situations, and surely the Flex people figured these things would not always be hard-coded?

EDIT2: To further simplify the problem, what I'm ideally looking for is a way to do the following:CursorManager.setCursor(someHandyFunction("myCursor.png")) If this is even possible, the question is what someHandyFunction should do?!

A: 

As far as I know it is currently not possible to create classes at runtime inside a flash vm using as3. Theoretically you might be able to create a swf with the class you need at runtime by writing swf-data to a bytearray and loading that, I do not recommend you to try that unless you are into a lot of puzzling and don't mind a lot of frustration ;-)

If you elaborate a bit on your requirements it might be possible to find another solution.

BTW: if you don't mind a solution that contains a server component: You could make your server compile new swf's that contain the right class and load those. There are multiple ways of making the flex compiler compile stuff on request.

Simon Groenewolt
+3  A: 

This one looked interesting, so I decided to take a whack at it. Here's what I was able to do -- there's probably a more elegant solution, but I've tested this, and it definitely works (here's a working example), so I figured I'd kick it back over to you to tinker with further if you like.

First, you'll need a custom class extending DisplayObject -- I just chose Bitmap, since I knew you were attempting to load and use JPG imagery:

package
{
    import flash.display.Bitmap;
    import mx.core.Application;

    public class MyLoadedImageClass extends Bitmap
    {  
     public function MyLoadedImageClass()
     {
      // ClassRef is simply the name of my Flex app
      super(ClassRef(Application.application).bitmapData);
     }
    }
}

... and then here's the Application code, which just loads things up and then calls setCursor():

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="init()">

    <mx:Script>
     <![CDATA[

      import mx.managers.CursorManager;
      import mx.managers.CursorManagerPriority;

      // This public member holds a reference to your loaded bitmapData,
      // which MyLoadedImageClass's constructor will use when instantiated
      // by the framework during CursorManager.setCursor()
      public var bitmapData:BitmapData;

      // Here we load the image
      private function init():void
      {
       var urlLoader:URLLoader = new URLLoader();
       var urlRequest:URLRequest = new URLRequest("http://roaming.turbonerd.com/m/20090104094515.jpg");

       urlLoader.addEventListener(Event.COMPLETE, urlLoader_complete);
       urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
       urlLoader.load(urlRequest); 
      }

      // Here we translate the bytes into a Bitmap
      private function urlLoader_complete(event:Event):void
      {
       var bytes:ByteArray = URLLoader(event.target).data;

       var loader:Loader = new Loader();
       loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loader_complete);
       loader.loadBytes(bytes); 
      }

      // And finally, we save off the bytes and set the cursor 
      private function loader_complete(event:Event):void
      {
       bitmapData = Bitmap(event.target.content).bitmapData;
       CursorManager.setCursor(MyLoadedImageClass, CursorManagerPriority.HIGH);
      }

     ]]>
    </mx:Script>

</mx:Application>

Hopefully the commenting describes things in enough detail. Hope it helps! (And thanks for the challenge!)

Christian Nunciato
Interesting approach, very grateful for your time. The only question I have is doesn't this method require one new class for each different cursor image, which kind of ends up being the same as using [Embed]?
MidnightGun
Actually no, the classes are only replacements for the kinds of classes you might use for your cursor. So if you're limiting yourself to static, URL-loadable imagery (JPG, PNG, GIF), then you'll only need one. If you wanted to have the option to use SWFs instead, you'd have two. Make sense? [...]
Christian Nunciato
I see what you mean, though: given the code I've provided, you've only got one bitmapData object in the parentApplication to use, so yes -- one object, one class. I really just wanted to demonstrate a working concept; it can easily be extended to handle as many images as you need. Hope that helps!
Christian Nunciato
Come to think of it, I'll bet if MyLoadedImageClass extended mx.controls.Image instead, you could use one class for both bitmaps and SWFs. Haven't tried that specifically, but it should work just as well.
Christian Nunciato
I'm not familiar with Flex, but can't he just use a Loader instance?var loader=new Loader();loader.load(new URLRequest("image.png");CursorManager.setCursor(loader, CursorManagerPriority.HIGH);
Cay
A: 

is possible do the same with the component ?

A: 

Check out this example class from Ben Stucki. I have used it extensively to dynamically create class instances from remote JPG/GIF/PNG.

http://blog.benstucki.net/?p=42

A: 

Hi there, i've recently fought with the CursorManager (tried to make him load png cursors at run-time), and as a result, i've posted a utility class at my labs blog.

Take a look, might be handy for ya: http://chargedweb.com/labs/2010/03/12/flex-cursormanager-vs-jloa/

Jloa