<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Saturnboy &#187; drag-and-drop</title>
	<atom:link href="http://saturnboy.com/tag/drag-and-drop/feed/" rel="self" type="application/rss+xml" />
	<link>http://saturnboy.com</link>
	<description>Code, Work, and Life</description>
	<lastBuildDate>Thu, 19 Aug 2010 03:28:54 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Drag-and-Drop in Flex 4</title>
		<link>http://saturnboy.com/2009/08/drag-and-drop-flex-4/</link>
		<comments>http://saturnboy.com/2009/08/drag-and-drop-flex-4/#comments</comments>
		<pubDate>Thu, 06 Aug 2009 02:40:52 +0000</pubDate>
		<dc:creator>justin</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[drag-and-drop]]></category>
		<category><![CDATA[flex4]]></category>
		<category><![CDATA[fxg]]></category>

		<guid isPermaLink="false">http://saturnboy.com/?p=672</guid>
		<description><![CDATA[The Flex 4 gods were kind to us developers when they made the great decision to leave the custom drag-and-drop support unchanged. We just do what we&#8217;ve always done: detect the user is trying to drag something via mouseDown or mouseMove and then add both dragEnter and dragDrop event handlers to the drop target. So [...]]]></description>
			<content:encoded><![CDATA[<p>The Flex 4 gods were kind to us developers when they made the great decision to leave the custom drag-and-drop support unchanged.  We just do what we&#8217;ve always done: detect the user is trying to drag something via <code>mouseDown</code> or <code>mouseMove</code> and then add both <code>dragEnter</code> and <code>dragDrop</code> event handlers to the drop target.  So there is nothing in this post that&#8217;s not basically identical to Flex 3, except the coolness of FXG (which you can easily mimic with <a href="http://www.degrafa.org/">Degrafa</a> in Flex 3).</p>
<h5>Simple Drag-and-Drop</h5>
<p class="bottom">I&#8217;ll begin with a basic Flex 4 application.  We have two draggable graphics (a <code>Rect</code> and an <code>Ellipse</code>) in the left panel, and a target panel on the right:</p>

<div class="wp_syntax"><div class="code"><pre class="mxml" style="font-family:monospace;"><span style="color: #000000;">&lt;?xml version=<span style="color: #ff0000;">&quot;1.0&quot;</span> encoding=<span style="color: #ff0000;">&quot;utf-8&quot;</span>?<span style="color: #7400FF;">&gt;</span></span>
<span style="color: #000000;"><span style="color: #7400FF;">&lt;s:Application</span></span>
<span style="color: #000000;">        xmlns:fx=<span style="color: #ff0000;">&quot;http://ns.adobe.com/mxml/2009&quot;</span></span>
<span style="color: #000000;">        xmlns:s=<span style="color: #ff0000;">&quot;library://ns.adobe.com/flex/spark&quot;</span><span style="color: #7400FF;">&gt;</span></span>
&nbsp;
    <span style="color: #000000;"><span style="color: #7400FF;">&lt;fx:Script</span><span style="color: #7400FF;">&gt;</span></span>
        <span style="color: #000000;">&lt;!<span style="color: #66cc66;">&#91;</span>CDATA<span style="color: #66cc66;">&#91;</span></span>
<span style="color: #000000;">            imports...</span>
&nbsp;
<span style="color: #000000;">            private function mouseDownHandler<span style="color: #66cc66;">&#40;</span>e:MouseEvent<span style="color: #66cc66;">&#41;</span>:void <span style="color: #66cc66;">&#123;</span></span>
<span style="color: #000000;">                DragManager.doDrag<span style="color: #66cc66;">&#40;</span>e.currentTarget as IUIComponent, null, e<span style="color: #66cc66;">&#41;</span>;</span>
<span style="color: #000000;">            <span style="color: #66cc66;">&#125;</span></span>
&nbsp;
<span style="color: #000000;">            private function dragEnterHandler<span style="color: #66cc66;">&#40;</span>e:DragEvent<span style="color: #66cc66;">&#41;</span>:void <span style="color: #66cc66;">&#123;</span></span>
<span style="color: #000000;">                DragManager.acceptDragDrop<span style="color: #66cc66;">&#40;</span>e.currentTarget as IUIComponent<span style="color: #66cc66;">&#41;</span>;</span>
<span style="color: #000000;">            <span style="color: #66cc66;">&#125;</span></span>
&nbsp;
<span style="color: #000000;">            private function dragDropHandler<span style="color: #66cc66;">&#40;</span>e:DragEvent<span style="color: #66cc66;">&#41;</span>:void <span style="color: #66cc66;">&#123;</span></span>
<span style="color: #000000;">                e.currentTarget.addElement<span style="color: #66cc66;">&#40;</span>e.dragInitiator<span style="color: #66cc66;">&#41;</span>;</span>
<span style="color: #000000;">            <span style="color: #66cc66;">&#125;</span></span>
<span style="color: #000000;">        <span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span><span style="color: #7400FF;">&gt;</span></span>
    <span style="color: #000000;"><span style="color: #7400FF;">&lt;/fx:Script</span><span style="color: #7400FF;">&gt;</span></span>
&nbsp;
    <span style="color: #000000;"><span style="color: #7400FF;">&lt;s:Panel</span> title=<span style="color: #ff0000;">&quot;src&quot;</span> width=<span style="color: #ff0000;">&quot;100&quot;</span> minHeight=<span style="color: #ff0000;">&quot;133&quot;</span> x=<span style="color: #ff0000;">&quot;10&quot;</span> y=<span style="color: #ff0000;">&quot;10&quot;</span><span style="color: #7400FF;">&gt;</span></span>
        <span style="color: #000000;"><span style="color: #7400FF;">&lt;s:Graphic</span> width=<span style="color: #ff0000;">&quot;80&quot;</span> height=<span style="color: #ff0000;">&quot;80&quot;</span></span>
<span style="color: #000000;">                mouseDown=<span style="color: #ff0000;">&quot;mouseDownHandler(event)&quot;</span><span style="color: #7400FF;">&gt;</span></span>
            <span style="color: #000000;"><span style="color: #7400FF;">&lt;s:Rect</span> ... <span style="color: #7400FF;">&lt;/s:Rect</span><span style="color: #7400FF;">&gt;</span></span>
        <span style="color: #000000;"><span style="color: #7400FF;">&lt;/s:Graphic</span><span style="color: #7400FF;">&gt;</span></span>
&nbsp;
        <span style="color: #000000;"><span style="color: #7400FF;">&lt;s:Graphic</span> width=<span style="color: #ff0000;">&quot;80&quot;</span> height=<span style="color: #ff0000;">&quot;80&quot;</span></span>
<span style="color: #000000;">                mouseDown=<span style="color: #ff0000;">&quot;mouseDownHandler(event)&quot;</span><span style="color: #7400FF;">&gt;</span></span>
            <span style="color: #000000;"><span style="color: #7400FF;">&lt;s:Ellipse</span> ... <span style="color: #7400FF;">&lt;/s:Ellipse</span><span style="color: #7400FF;">&gt;</span></span>
        <span style="color: #000000;"><span style="color: #7400FF;">&lt;/s:Graphic</span><span style="color: #7400FF;">&gt;</span></span>
        ...
    <span style="color: #000000;"><span style="color: #7400FF;">&lt;/s:Panel</span><span style="color: #7400FF;">&gt;</span></span>
&nbsp;
    <span style="color: #000000;"><span style="color: #7400FF;">&lt;s:Panel</span> title=<span style="color: #ff0000;">&quot;target&quot;</span> width=<span style="color: #ff0000;">&quot;100&quot;</span> minHeight=<span style="color: #ff0000;">&quot;133&quot;</span> x=<span style="color: #ff0000;">&quot;120&quot;</span> y=<span style="color: #ff0000;">&quot;10&quot;</span></span>
<span style="color: #000000;">            dragEnter=<span style="color: #ff0000;">&quot;dragEnterHandler(event);&quot;</span></span>
<span style="color: #000000;">            dragDrop=<span style="color: #ff0000;">&quot;dragDropHandler(event);&quot;</span><span style="color: #7400FF;">&gt;</span></span>
        ...
    <span style="color: #000000;"><span style="color: #7400FF;">&lt;/s:Panel</span><span style="color: #7400FF;">&gt;</span></span>
<span style="color: #000000;"><span style="color: #7400FF;">&lt;/s:Application</span><span style="color: #7400FF;">&gt;</span></span></pre></div></div>

<p>Reading the code above, each draggable <code>Graphic</code> has a <code>mouseDown</code> handler that calls <code>DragManager.doDrag()</code> to initiate dragging.   And the target <code>Panel</code> calls <code>DragManager.acceptDragDrop()</code> on <code>dragEnter</code> and <code>addElement()</code> on <code>dragDrop</code>.  Note that since <code>Panel</code> is a Spark container we must use <code>addElement()</code> to re-parent the dropped graphic (the familiar <code>addChild()</code> is still used for Halo containers).</p>
<p class="bottom">Our simple drag-and-drop app (view source enabled):</p>
<div id="flashcontent-drag-drop">
Flash is required.  <a href="http://www.adobe.com/go/getflashplayer">Get it here!</a>
</div>
<h5>Using a FXG Drag Proxy</h5>
<p>In the example above, the moment you start dragging a component the drag proxy is displayed.  By default, the proxy is just a bounding rectangle with an alpha value of 0.5.  This is particularly noticeable and <i>lame</i> when you try to drag the pink circle.  Thankfully, we can use any display object for the drag proxy (more specifically any component that implements <code>IFlexDisplayObject</code> which includes <code>UIComponent</code> and any of its descendants).  Why not use a FXG graphic?  It is, after all, a major piece of the new hotness that is Flex 4.</p>
<p class="bottom">First, we need to modify the <code>mouseDownHandler</code> to instantiate our FXG graphic.  Then we just add it as the forth parameter to the <code>DragManager.doDrag()</code> call.</p>

<div class="wp_syntax"><div class="code"><pre class="actionscript" style="font-family:monospace;"><span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">function</span> mouseDownHandler<span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">e</span>:MouseEvent<span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">var</span> star:Star = <span style="color: #000000; font-weight: bold;">new</span> Star<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
    DragManager.<span style="color: #006600;">doDrag</span><span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">e</span>.<span style="color: #006600;">currentTarget</span> as IUIComponent, <span style="color: #000000; font-weight: bold;">null</span>, <span style="color: #0066CC;">e</span>, star<span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span></pre></div></div>

<p class="bottom">And here is <code>Star.mxml</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="mxml" style="font-family:monospace;"><span style="color: #000000;">&lt;?xml version=<span style="color: #ff0000;">&quot;1.0&quot;</span> encoding=<span style="color: #ff0000;">&quot;utf-8&quot;</span>?<span style="color: #7400FF;">&gt;</span></span>
<span style="color: #000000;"><span style="color: #7400FF;">&lt;s:Graphic</span></span>
<span style="color: #000000;">        xmlns:fx=<span style="color: #ff0000;">&quot;http://ns.adobe.com/mxml/2009&quot;</span></span>
<span style="color: #000000;">        xmlns:s=<span style="color: #ff0000;">&quot;library://ns.adobe.com/flex/spark&quot;</span></span>
<span style="color: #000000;">        width=<span style="color: #ff0000;">&quot;80&quot;</span> height=<span style="color: #ff0000;">&quot;80&quot;</span><span style="color: #7400FF;">&gt;</span></span>
&nbsp;
    <span style="color: #000000;"><span style="color: #7400FF;">&lt;s:Path</span> data=<span style="color: #ff0000;">&quot;M 119,0 L 148,86 238,86 166,140 192,226 119,175 46,226 72,140 0,86 90,86 Z&quot;</span></span>
<span style="color: #000000;">            y=<span style="color: #ff0000;">&quot;2&quot;</span> scaleX=<span style="color: #ff0000;">&quot;0.3361345&quot;</span> scaleY=<span style="color: #ff0000;">&quot;0.3361345&quot;</span><span style="color: #7400FF;">&gt;</span></span>
        <span style="color: #000000;"><span style="color: #7400FF;">&lt;s:fill</span><span style="color: #7400FF;">&gt;</span></span>
            <span style="color: #000000;"><span style="color: #7400FF;">&lt;mx:SolidColor</span> color=<span style="color: #ff0000;">&quot;#FFCC00&quot;</span> <span style="color: #7400FF;">/&gt;</span></span>
        <span style="color: #000000;"><span style="color: #7400FF;">&lt;/s:fill</span><span style="color: #7400FF;">&gt;</span></span>
    <span style="color: #000000;"><span style="color: #7400FF;">&lt;/s:Path</span><span style="color: #7400FF;">&gt;</span></span>
<span style="color: #000000;"><span style="color: #7400FF;">&lt;/s:Graphic</span><span style="color: #7400FF;">&gt;</span></span></pre></div></div>

<p class="bottom">Bang!  We have a gold star as our drag proxy.  Try it out for yourself (view source enabled):</p>
<div id="flashcontent-drag-drop-star">
Flash is required.  <a href="http://www.adobe.com/go/getflashplayer">Get it here!</a>
</div>
<h5>Dynamic Drag Proxy</h5>
<p>Dragging a gold star is pretty cool, but how can we make the drag proxy look <b>exactly</b> like the drag source?  For that we need a dynamic drag proxy.</p>
<p class="bottom">First, for reasons which will become clear in a moment, we need to revise our app to make each of the drag source graphics into a separate component.  So the left <code>Panel</code> changes to contain these custom components:</p>

<div class="wp_syntax"><div class="code"><pre class="mxml" style="font-family:monospace;"><span style="color: #000000;"><span style="color: #7400FF;">&lt;s:Panel</span> title=<span style="color: #ff0000;">&quot;src&quot;</span> width=<span style="color: #ff0000;">&quot;100&quot;</span> minHeight=<span style="color: #ff0000;">&quot;133&quot;</span> x=<span style="color: #ff0000;">&quot;10&quot;</span> y=<span style="color: #ff0000;">&quot;10&quot;</span><span style="color: #7400FF;">&gt;</span></span>
    <span style="color: #000000;"><span style="color: #7400FF;">&lt;graphics:Square</span> fillColor=<span style="color: #ff0000;">&quot;#6666FF&quot;</span></span>
<span style="color: #000000;">            mouseDown=<span style="color: #ff0000;">&quot;mouseDownHandler(event)&quot;</span> <span style="color: #7400FF;">/&gt;</span></span>
&nbsp;
    <span style="color: #000000;"><span style="color: #7400FF;">&lt;graphics:Circle</span> fillColor=<span style="color: #ff0000;">&quot;#FF66FF&quot;</span></span>
<span style="color: #000000;">            mouseDown=<span style="color: #ff0000;">&quot;mouseDownHandler(event)&quot;</span> <span style="color: #7400FF;">/&gt;</span></span>
&nbsp;
    <span style="color: #000000;"><span style="color: #7400FF;">&lt;graphics:Star</span> fillColor=<span style="color: #ff0000;">&quot;#FFCC00&quot;</span></span>
<span style="color: #000000;">            mouseDown=<span style="color: #ff0000;">&quot;mouseDownHandler(event)&quot;</span> <span style="color: #7400FF;">/&gt;</span></span>
&nbsp;
    <span style="color: #000000;"><span style="color: #7400FF;">&lt;graphics:Square</span> fillColor=<span style="color: #ff0000;">&quot;#66FF99&quot;</span></span>
<span style="color: #000000;">            mouseDown=<span style="color: #ff0000;">&quot;mouseDownHandler(event)&quot;</span> <span style="color: #7400FF;">/&gt;</span></span>
&nbsp;
    <span style="color: #000000;"><span style="color: #7400FF;">&lt;s:layout</span><span style="color: #7400FF;">&gt;</span></span>
        <span style="color: #000000;"><span style="color: #7400FF;">&lt;s:VerticalLayout</span> gap=<span style="color: #ff0000;">&quot;10&quot;</span> horizontalAlign=<span style="color: #ff0000;">&quot;center&quot;</span> paddingTop=<span style="color: #ff0000;">&quot;10&quot;</span> paddingBottom=<span style="color: #ff0000;">&quot;10&quot;</span> <span style="color: #7400FF;">/&gt;</span></span>
    <span style="color: #000000;"><span style="color: #7400FF;">&lt;/s:layout</span><span style="color: #7400FF;">&gt;</span></span>
<span style="color: #000000;"><span style="color: #7400FF;">&lt;/s:Panel</span><span style="color: #7400FF;">&gt;</span></span></pre></div></div>

<p class="bottom">Next, we again modify the <code>mouseDownHandler</code>, this time we instantiate our drag proxy dynamically.  We use reflection on the incoming drag source to get its name, instantiate it, adjust a few properties, and pass it to the <code>DragManager.doDrag()</code> call.</p>

<div class="wp_syntax"><div class="code"><pre class="actionscript" style="font-family:monospace;"><span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">function</span> mouseDownHandler<span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">e</span>:MouseEvent<span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">var</span> dragSrc:Graphic = <span style="color: #0066CC;">e</span>.<span style="color: #006600;">currentTarget</span> as Graphic;
&nbsp;
    <span style="color: #808080; font-style: italic;">//create a proxy by creating a new &quot;copy&quot; of the drag src</span>
    <span style="color: #000000; font-weight: bold;">var</span> className:<span style="color: #0066CC;">String</span> = getQualifiedClassName<span style="color: #66cc66;">&#40;</span>dragSrc<span style="color: #66cc66;">&#41;</span>;
    <span style="color: #000000; font-weight: bold;">var</span> klass:<span style="color: #000000; font-weight: bold;">Class</span> = getDefinitionByName<span style="color: #66cc66;">&#40;</span>className<span style="color: #66cc66;">&#41;</span> as <span style="color: #000000; font-weight: bold;">Class</span>;
    <span style="color: #000000; font-weight: bold;">var</span> proxy:<span style="color: #66cc66;">*</span> = <span style="color: #000000; font-weight: bold;">new</span> klass<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
    <span style="color: #808080; font-style: italic;">//set the proxy's properties to match the src + sexy drop shadow</span>
    proxy.<span style="color: #0066CC;">width</span> = dragSrc.<span style="color: #0066CC;">width</span>;
    proxy.<span style="color: #0066CC;">height</span> = dragSrc.<span style="color: #0066CC;">height</span>;
    proxy.<span style="color: #006600;">fillColor</span> = <span style="color: #66cc66;">&#40;</span>dragSrc as IDraggableGraphic<span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">fillColor</span>;
    proxy.<span style="color: #006600;">filters</span> = <span style="color: #66cc66;">&#91;</span><span style="color: #000000; font-weight: bold;">new</span> DropShadowFilter<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#93;</span>;
&nbsp;
    DragManager.<span style="color: #006600;">doDrag</span><span style="color: #66cc66;">&#40;</span>dragSrc, <span style="color: #000000; font-weight: bold;">null</span>, <span style="color: #0066CC;">e</span>, proxy<span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span></pre></div></div>

<p>The real reason for the reflection gymnastics, plus the need to package each drag source as a custom component, is the lack of a <b>deep copy</b> operation on <code>UIComponent</code>.  If we could just <i>clone</i> the drag source, we&#8217;d be golden.  Alas, for many reasons, the most obvious of which is that it is a huge pain in the ass, there is no such thing as deep copy.  In our case, my work around was to package all the visual stuff of each draggable item into a single custom component with a known API (all the custom graphics implement <code>IDraggableGraphic</code>).  Then I reflect, instantiate, configure, and pass to <code>doDrag()</code>.</p>
<p class="bottom">Our dynamic drag proxy now matches the drag source, plus the sexy drop shadow.  Check it out (view source enabled):</p>
<div id="flashcontent-drag-drop-proxy">
Flash is required.  <a href="http://www.adobe.com/go/getflashplayer">Get it here!</a>
</div>
<h5>Files</h5>
<ul>
<li><a href="http://saturnboy.com/proj/flex4/drag_drop/simple/DragDrop.html">DragDrop</a> (<a href="http://saturnboy.com/proj/flex4/drag_drop/simple/srcview/DragDrop.zip">download</a>)</li>
<li><a href="http://saturnboy.com/proj/flex4/drag_drop/star/DragDropStar.html">DragDropStar</a> (<a href="http://saturnboy.com/proj/flex4/drag_drop/star/srcview/DragDropStar.zip">download</a>)</li>
<li><a href="http://saturnboy.com/proj/flex4/drag_drop/proxy/DragDropProxy.html">DragDropProxy</a> (<a href="http://saturnboy.com/proj/flex4/drag_drop/proxy/srcview/DragDropProxy.zip">download</a>)</li>
</ul>
<blockquote><p><b>NOTE:</b> All code was built with Flash Builder 4 Beta 1.</p></blockquote>
<div>
<script type="text/javascript">
swfobject.embedSWF('http://saturnboy.com/proj/flex4/drag_drop/simple/DragDrop.swf', 'flashcontent-drag-drop', '400', '260', '10.0.0', 'expressInstall.swf', false, { bgColor:'#ffffff', base:'.' });
</script><br />
<script type="text/javascript">
swfobject.embedSWF('http://saturnboy.com/proj/flex4/drag_drop/star/DragDropStar.swf', 'flashcontent-drag-drop-star', '400', '260', '10.0.0', 'expressInstall.swf', false, { bgColor:'#ffffff', base:'.' });
</script><br />
<script type="text/javascript">
swfobject.embedSWF('http://saturnboy.com/proj/flex4/drag_drop/proxy/DragDropProxy.swf', 'flashcontent-drag-drop-proxy', '400', '450', '10.0.0', 'expressInstall.swf', false, { bgColor:'#ffffff', base:'.' });
</script></div>
]]></content:encoded>
			<wfw:commentRss>http://saturnboy.com/2009/08/drag-and-drop-flex-4/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
	</channel>
</rss>
