DragManager & DragSource
Last weekend and this, I’ve been playing with some Flex apps to showcase at the next Atlanta Macromedia User’s Group meeting so I can give a more accurate showcase of what Flex can do, and how it feels for a Flash Developer to use. One particular component I was going to code in Flash… and figured instead it was a good opportunity to try to learn how Flex handles drag and drop. This was always the hardest thing for me to code in Flash (and my favorite ’cause it’s hard); I wanted to see how “easy” they made this in Flex.
There are really 3 things you need to know about dragging in Flex: The DragManager, the DragSource, and whether your doing it or the components are.
Now, I haven’t delved into a lot of the automated stuff b/c I like to know what is going on, and I wanted to get down and dirty (gross) with the code to garner a better understanding. I ended up doing a little of both since the TileList control, like a List in Flash MX 2004, only it tiles and resizes & repositions the images for you (that’s what I load in anyway). If you simply say dragEnabled=”true” for the attribute, Flex’ll deal with all the drag and move operations; you’ve just gotta handle the drop.
Flex has a really neat, and strict order of operations for drag and drop to ease the coding process. The docs have a great description that I had to read twice, but here’s the gist:
– component recognizes drag
– creates a proxy (a component created via a PopUpManager type method)
– when you drag it around, UIComponent’s get dragOver, dragEnter, and dragExit events
– if any dragOver event set’s the event object’s handled method to true, it’ll receive a dragDrop event if the user drops it there
– the dude who triggered the event, in this case my TileList, will get a dragBegin and dragComplete; everyone’s informed of what’s going on
– if the user drops it and it’s handled, cool, if not, cool; either way, the Proxy gets removed.
…now, the challenge for me was understanding the dragOver setting the event.handled to true; had to dig in the manual to find that one. Secondly, and the most challenging, was the DragSource class. Matt Chotin gave a good and thorough explanation about what the DragSource really is and does for those of you who want a less technical explanation.
Basically, it solves 2 goals to summarize: Holds information about who started the drag, what data is being dragged (such as List item), and what function to call if you want more information about the data just in case the actual call itself is processor itensive; that way if the user aborts the drag, it’s not an overally processor intensive operation.
I’m still learning that bad boy, but for now, if you can deal with the getFormat(“source”) and getFormat(“items”) use of the method, your good to go.
The one gotcha for me was positioning; I haven’t had to use localToGlobal yet in my code, but I definately did a lot of adding and subtracting of x and y values of my various containers, since Flex is all about the containers, baby. Maybe it does this for you, but I couldn’t find it. This gets more challenging since the doDrag method of the DragManager Singleton class is called automatically if you use the automated method; setting a UIComponent’s dragEnabled property to true; since it’s called for you, you can’t really capture the last X and Y offset’s the user clicked. Matt said I could get the Proxy, but I’m still trying to find that crackheaded movieclip on _root somehwere…
To summarize, I like the drag and drop scheme Flex has going for these reasons:
– defined drag and drop process with event handlers
– EVERYONE is in the game; if your a UIComponent, you can play. Since everyone pretty much is in Flex, everyone’s in the door.
– it meshes really nicely with dragging items, aka DataProvider objects. Dragging a List item is technically dragging a DataProvider item, and thus, you immediately know what your dealing with code wise; it’s familiar to deal with items.
– I don’t have to code this myself, just handling the drop.
– Since Flex has a lot of containers, and a lot of them inherit from View, you get the add and remove child methods which makes it uber simple to add and remove components from within components.
Negative Spacer Width
You know those logos in Central that each application has when in the App view? (No Jester…), well anyway, they are at the top left, and they align with the application usually on the left side. Was having a problem with an image aligning to the panel below it. I remember hacks in HTML of using negative values. So, I set a spacer’s width to -4 for an x and she aligns great with the Panel below it!
<mx:Spacer width="-4" />
<mx:Image source="@Embed('images/logo_app.png')" width="271" height="50" />
<mx:Panel id="main_panel" width="100%" height="100%" y="0" x="0">