Flex 4 Drag-n-Drop with custom DragProxy - apache-flex

I'm doing the drag an drop of an ItemRenderer manually (DataGrid) and want to know how to generate a custom DragProxy of a component that hasn't been added to the display list.
I tried something like this but didn't work:
private function doDrag(event:MouseEvent):void
{
var dragSource:DragSource = new DragSource();
dragSource.addData(data, 'dnd_format');
//var bm:Bitmap = new Bitmap(ImageSnapshot.captureBitmapData(this));
var btn:Button = new Button();
btn.label = 'New Button';
var bm:Bitmap = new Bitmap(ImageSnapshot.captureBitmapData(btn));
var dragProxy:Image = new Image();
dragProxy.source = bm;
DragManager.doDrag(this, dragSource, event, dragProxy,0,0, 0.6);
}
So, I want to be able to create the DragProxy using a component, the button is just an example.
Any ideas?

My guess is that this is not working because you are trying to get a bitmap from a component that was just created and has not been added to the stage. I would try testing this code with using an embedded image as the drag proxy first. If that works, then try getting a bitmap from a component that exists on the stage. My guess is that both cases will work.

Related

Flex 4.6 Need to know how to animate a .swf in actionscript

I've converted a PowerPoint into Flash so each slide is a .swf. I've used a number of different converters and the problem here is the same.
What I'd like to do is trigger the .swf's animation (contents of slide appearing) programatically. I can click on the .swf with a mouse and the animation advances. I can automate this when the .swf's embedded in a web page simply by doing:
document.getElementById('myMovie').play();
Each time I execute that code, the swf advances to the next animation. However, I can't find a way to do this in flex. I've used then MovieClipSWFLoader and tried:
private function animate():void {
var simulatedClick1:MouseEvent = new MouseEvent(MouseEvent.CLICK);
var simulatedClick2:MouseEvent = new MouseEvent(MouseEvent.MOUSE_DOWN);
var simulatedClick3:MouseEvent = new MouseEvent(MouseEvent.MOUSE_UP);
frameNo++;
myMovie.gotoAndStop(frameNo);
myMovie.nextFrame();
myMovie.nextScene();
myMovie.play();
myMovie.dispatchEvent(simulatedClick1); // with clicks 1, 2, and 3
}
<s:MovieClipSWFLoader id="myMovie" source=""/>
<s:Button id="btnAnimate" click="animate()"/>
I've also tried loading as an Image component and using the simulated click too... no good. Can anyone tell me how I can do this?
The problem was that the .swf was created with Flash 8 and wasn't compatible with my version of Flex. I found a great solution in ForcibleLoader at https://gist.github.com/nsdevaraj/409902. It converts old .swf's to new ones and then the code worked as it should.
private var libMC:MovieClip = new MovieClip();
ur = new URLRequest(guide_url);
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, swfComplete);
var fLoader:ForcibleLoader = new ForcibleLoader(loader);
fLoader.load(ur);
swfMovie.addChild(loader);
private function swfComplete(event:Event):void{
libMC = event.currentTarget.content as MovieClip;
}
private function animate():void {
libMC.nextFrame();
<mx:UIComponent id="swfMovie"/>

How to dynamically load image for drag and drop?

I am implementing drag and drop from a DataGrid onto a List in a Flex 3 AIR application. I would like to have the drag image be a photo (jpg) referenced by a String field in the data grid item, named 'imagePath'. I'm having trouble getting the image to show up during dragging. I have triple checked that it is not because of an invalid path to the image. I have tried Image's source() and load() methods in every way I can think of. I am calling this method 'dragCurrentToList(event)' on a mouseDown event.
private function dragCurrentToList(event:MouseEvent):void
{
var current:Object = event.currentTarget.selectedItem;
var dragImg:Image = new Image();
dragImg.load(current.imagePath);
dragImg.width = 100;
dragImg.width = 100;
var dsource:DragSource = new DragSource();
dsource.addData(current, 'record');
DragManager.doDrag(event.currentTarget as DataGrid, dsource, event, dragImg);
}
This works perfectly if I set the image source to the following bindable variable but I don't want to hardcode the image name.
[Bindable]
[Embed(source='assets/icons/default.jpg')]
public var dragIcon:Class;
...
dragImg.source = dragIcon
...
In your dragCurrentToList method, why are you loading the image instead of just specifying the source attribute as the URL to the image?
http://livedocs.adobe.com/flex/3/langref/mx/controls/SWFLoader.html#source
private function dragCurrentToList(event:MouseEvent):void
{
var current:Object = event.currentTarget.selectedItem;
var dragImg:Image = new Image();
dragImg.source = current.imagePath;
dragImg.width = 100;
dragImg.width = 100;
var dsource:DragSource = new DragSource();
dsource.addData(current, 'record');
DragManager.doDrag(event.currentTarget as DataGrid, dsource, event, dragImg);
}
Also make sure you are responding to the dragStart event. ( http://livedocs.adobe.com/flex/3/langref/mx/core/UIComponent.html#event:dragStart ). And I believe instead of accessing the DragManager class; you should simply modify the dragSource property of the dragStart event.

Getting Flex TileList image source

I have a TileList that's loaded with data from Flickr. The tilelist uses an imageRenderer to make a bunch of thumbnails.
I'm trying to create a custom drag and drop function, but I want to get the image source of the tilelist mouseEvent target. Here's what the code looks like for the drag handler:
public function onPicMouseDown(e:MouseEvent):void {
var tileList:TileList = TileList(e.currentTarget);
var item:Object = Object(tileList.selectedItem);
var source:DragSource = new DragSource();
var dragView : Image = new Image();
dragView.source = tileList.selectedItem.source;
DragManager.doDrag(
rowRenderer,
source,
e,
dragView
);
}
But tileList.selectedItem doesn't have a source property. The source is a property of the image produced by the itemrenderer. I'd like to be able to do something that's the equivalent of
tileList.selectedItem.itemRenderer.source
But that doesn't do it either.
There's got to be a simple way to do this that I'm just missing. Any help would be much appreciated.
In your onMousePicDown handler your source should be:
dragView.source = event.target.parent.source;

Create a button with an icon in actionscript

I want to create buttons with icons in Flex dynamically using Actionscript.
I tried this, with no success:
var closeButton = new Button();
closeButton.setStyle("icon", "#Embed(source='images/closeWindowUp.png");
I found an answer that works for me. In my .mxml file, I create Classes for the icons I will use:
// Classes for icons
[Embed(source='images/closeWindowUp.png')]
public static var CloseWindowUp:Class;
[Embed(source='/images/Down_Up.png')]
public static var Down_Up:Class;
[Embed(source='/images/Up_Up.png')]
public static var Up_Up:Class;
In the Actionscript portion of my application, I use these classes when dynamically creating buttons:
var buttonHBox:HBox = new HBox();
var closeButton:Button = new Button();
var upButton:Button = new Button();
var downButton:Button = new Button();
closeButton.setStyle("icon", SimpleWLM.CloseWindowUp);
buttonHBox.addChild(closeButton);
upButton.setStyle("icon", SimpleWLM.Up_Up);
buttonHBox.addChild(upButton);
downButton.setStyle("icon", SimpleWLM.Down_Up);
buttonHBox.addChild(downButton);
You can use this one option of dynamic change of button icon.
Embed your icons
[Embed(source='com/images/play.png')]
[Bindable]
public var imagePlay:Class;
[Embed(source='com/images/pause.png')]
[Bindable]
public var imagePause:Class;
Using one button to toggle play and pause of video
private function playpause():void
{
if (seesmicVideo.playing)
{
seesmicVideo.pause();
btn_play.setStyle("icon",imagePlay);
}
else
{
seesmicVideo.play();
btn_play.setStyle("icon",imagePause);
}
}
The error is in the quotes, there should be no quotes around the #Embed:
closeButton.setStyle("icon", #Embed(source="images/closeWindowUp.png"));
I was able to use an icon in my button with the following code:
<mx:Button id="buttonPlay" label="Play" click="playButtonClicked();" enabled="false" icon="#Embed('./play.png')"/>
the file play.png is in the same folder of the mxml file.
I am using Flash Builder version 4.6.
Edit: the question was about ActionScript and not MXML, but I leave this answer just for reference.
I'm assuming you're adding it to the stage?
Also, I think your Embed is missing a close quote / paren.
closeButton.setStyle("icon", "#Embed(source='images/closeWindowUp.png");
should be:
closeButton.setStyle("icon", "#Embed(source='images/closeWindowUp.png')");

How do I implement custom drag functionality in a Flex list control?

Flex has built in drag-n-drop for list controls, and allows you to override this. But they don't cover this in examples. The built-in functionality automatically drags the list-item, if you want to override this you find the handlers are being set up on the list itself.
What I specifically want to do, is my TileList shows small thumbnails of items I can drag onto a large Canvas. As I drag an item from the list, the drag proxy should be a different image.
So, I followed the technique suggested and it only works if I explicitly set the width/height on the proxy Image. Why?
It's not obvious until you've tried it =) I struggled with the same thing just a few weeks ago. This was my solution:
The list:
<List>
<mouseDown>onListMouseDown(event)</mouseDown>
</Tree>
The mouse down handler:
private function onMouseDown( event : MouseEvent ) : void {
var list : List = List(event.currentTarget);
// the data of the clicked row, change the name of the class to your own
var item : MyDataType = MyDataType(list.selectedItem);
var source : DragSource = new DragSource();
// MyAwsomeDragFormat is the key that you will retrieve the data by in the
// component that handles the drop
source.addData(item, "MyAwsomeDragFormat");
// this is the component that will be shown as the drag proxy image
var dragView : UIComponent = new Image();
// set the source of the image to a bigger version here
dragView.source = getABiggerImage(item);
// get hold of the renderer of the clicked row, to use as the drag initiator
var rowRenderer : UIComponent = UIComponent(list.indexToItemRenderer(list.selectedIndex));
DragManager.doDrag(
rowRenderer,
source,
event,
dragView
);
}
That will start the drag when the user clicks an item in the list. Notice that I don't set dragEnabled and the other drag-related properties on the list since I handle all that myself.
It can be useful to add this to the beginning of the event handler:
if ( event.target is ScrollThumb || event.target is Button ) {
return;
}
Just to short circuit if the user clicks somewhere in the scrollbar. It's not very elegant but it does the job.
I found a simpler answer here. That example extends a DataGrid control, but you can do the same with a List control. In my case, I use an image source instead of Class:
public class CustomDragList extends List {
[Bindable]
public var dragProxyImageSource:Object;
override protected function get dragImage():IUIComponent {
var image:Image = new Image();
image.width = 50;
image.height = 50;
image.source = dragProxyImageSource;
image.owner = this;
return image;
}
}
Then use that custom list like this:
<control:CustomDragList
allowMultipleSelection="true"
dragEnabled="true"
dragProxyImageSource="{someImageSource}"
dragStart="onDragStart(event)"/>
Where 'someImageSource' can be anything you'd normally use for an image source (embedded, linked, etc.)

Resources