Wednesday, February 25, 2009

Darren on Flex: Flexins, Drag 'n' Drop Mixin

I present to you the Drag'n'Drop Mixin

I've managed to embed an instance of my Drag'n'Drop showcase app here, but I cannot seem to influence the size of it. I recommend you visit the mixin's demo page here For those of you who are not interested in my posturing and story-telling, you can review the source for this application here at GitHub.

So how does it work?

You simply include <dnd:DnDMixin /> as a child of any container type and this enables that container as a drop target and any child as a drag source. It's as simple as that.

That's how you use it... How does it work?

Ok, here's an excerpt from the project's README file:
These mixins are designed to be used in MXML, leveraging components' event-driven life-cylce. They should be used as 'drop-ins', similar to usage model for inline item-renderers.
In addition to this, I exploit the Container.rawChildren property, due to the fact that this mixin is a content-less UI component and should not interfere with content-full UI components. When an application is loaded all declared UI components are processed through an event-driven life-cycle. The life-cycle events the dnd-mixin is interested in are:
FlexEvent.ADD:
Registration happens in the constructor, the earliest possible opportunity at the object level. More significantly, registration occurs before this (typically, one time) event is dispatched. The handler for this event deregisters from this same event, removes the dnd-mixin from the container and then adds it back but to the rawChildren. The handler then registers interest in the DragEvent.DRAG_ENTER, DragEvent.DRAG_OVER, DragEvent.DRAG_EXIT and DragEvent.DRAG_DROP events. The corresponding handlers implement the necessary mechanics to provide drag'n'drop functionality; I refer you to the source code as it's pretty straight forward and not that interesting, especially if you've implemented D'n'D yourself before. The handler also registers interest in the following events:
ChildExistenceChangedEvent.CHILD_ADD:
Through this event the dnd-mixin is notified whenever a component is added to the parent container. The addition of a child as far as the dnd-mixin is concerned, indicates a successful drag'n'drop operation to this parent container. Thus this event signals this dnd-mixin instance to take control of the D'n'D processing for this child component (to which a reference can be obtained from the event object). This handler registers interest in the following events on each managed child component:
MouseEvent.MOUSE_MOVE:
The registered handler simply detects the drag gesture (initiation) and delegates the operation to the DragManager.
DragEvent.DRAG_COMPLETE:
The registered handler basically just adds the dragged component to the new container, which implicitly removes it from its current/previous parent. Doing so dispatches the ChildExistenceChangedEvents, as explained here.
ChildExistenceChangedEvent.CHILD_REMOVE:
Similar to CHILD_ADD, this CHILD_REMOVE event notifies the dnd-mixin whenever a component is removed from the parent container. The removal of a child likewise indicates a successful drag'n'drop operation away from this parent container. Hence this event signals this dnd-mixin instance to relinquish control for D'n'D processing. This is explicit and is implemented through deregistering interest in the MouseEvent.MOUSE_MOVE and DragEvent.DRAG_COMPLETE events.
And that's all there is to it. Try it out above or here. As you'll see there is nothing spectacular about the end result; it's functional. The benefit is the improved readability in your code gained from the clean separation, reduced duplication and declarative style the mixins adopt. While I declare this dnd-mixin is fully functional I don't presume it will suit the needs of all drag'n'drop use cases. I have also observed a bug in the rendering of dragged items that were previously clipped by the parent's right edge. I think I recall a colleague encountering this problem (and solving it) so I'll ask her about it at the next available chance.

What's next?

Drag source filtering. This will support the use case if you want to allow some types of things to be dropped, but not others. The implementation for this is actually complete (see here); a blog will follow soon. If you want to use it, you know where the source/binaries are. Enjoy

Monday, February 16, 2009

How To: Use Google Code as a Maven Repository

While working on my new Flexins Project and blogging accordingly, I decided to explore using Maven and Flex-Mojos to build the libraries and showcase applications. I have a local install of Nexus, where I hide away most of the complexity that would otherwise be in my settings.xml files. I typically deploy to this repo for my own benefit where I might chose to make it public in the future so I can work on stuff (drag in deps) from anywhere. However, it is not a viable option if my or your aim is to truly make one's binaries publicly available (saving the curious the trouble of a compiling source). Some how I stumbled on to Don Brown's Weblog, where he talks about turning a Google Code project, that is the site itself with its SVN, into a Maven repository. I have not yet done this myself, but the details are here. Cheers

How To: Demo Flex Apps On Blogger or Google Sites

While working on my new Flexins Project and blogging accordingly, I discovered that you can embed you Flex application into your page quite easily. Here are the rawest of raw instructions on how to do it.
Flex on Blogger
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
    id="Main" width="100%" height="100%"
    codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">
    <param name="movie" value="https://sites.google.com/site/flexinsproject/flexins-catalog/dndmixin/dnd-mixin-demo-0.2.swf?attredirects=0" />
    <param name="quality" value="high" />
    <param name="bgcolor" value="#869ca7" />
    <param name="allowScriptAccess" value="sameDomain" />
    <embed src="https://sites.google.com/site/flexinsproject/flexins-catalog/dndmixin/dnd-mixin-demo-0.2.swf?attredirects=0" quality="high" bgcolor="#869ca7"
        width="100%" height="100%" name="Main" align="middle"
        play="true"
        loop="false"
        quality="high"
        allowScriptAccess="sameDomain"
        type="application/x-shockwave-flash"
        pluginspage="http://www.adobe.com/go/getflashplayer">
    </embed>
</object>
UPDATE, 27.02.2009: It seems Blogger ignores the <object>...</object> tags, so the nested <embed>...</embed> is sufficient. While I would not normally recommend removing robustness... parts of the <object>...</object> code was showing in my blog, so I got rid of it altogether. Also make sure the remaining <embed>...</embed> is format correctly i.e. no erroneous newlines; this was causing some of the parameters e.g. width and height, to be ignored.
Flex on Google Sites
<Module>
    <ModulePrefs title="__UP_title__"
    width="600"
    height="450"
    scrolling="true"
    author="Darren Bishop"
    author_email="dbishop81@gmail.com"
    description="GG to help embed Flex applications into Blogger or Google Sites">
        <Require feature="flash" />
    </ModulePrefs>
    <UserPref name="title" display_name="Title" default_value="Flex Application Embedder" />
    <UserPref name="swf_url" display_name="SW URL" />
    <Content type="html">
    <![CDATA[
    <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
        id="Main" width="100%" height="100%"
        codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">
        <param name="movie" value="__UP_swf_url__" />
        <param name="quality" value="high" />
        <param name="bgcolor" value="#869ca7" />
        <param name="allowScriptAccess" value="sameDomain" />
        <embed src="__UP_swf_url__" quality="high" bgcolor="#869ca7"
            width="100%" height="100%" name="Main" align="middle"
            play="true"
            loop="false"
            quality="high"
            allowScriptAccess="sameDomain"
            type="application/x-shockwave-flash"
            pluginspage="http://www.adobe.com/go/getflashplayer">
        </embed>
    </object>
    ]]>
    </Content>
</Module>
Wordpress
Sorry, you are on your own. Somehow, I don't think it would be that hard to do. If you can't figure it out, feel free to ask for help. Cheers

Darren on Flex: Flexins Project Launch

I am proud to announce the launch of the Flexins Project!

This project is the result of some work I started several months ago. I started looking into ways to leverage Flex's declarative MXML to add extra behaviour to applications (or parts therein), using mixins. The project's homepage is over at Flexins Project @ Google Sites. It's in flux at the moment as I'm still getting my bearings in administering the site; please bare with me on that one. The source code is hosted at Flexins Project @ Github. I decided to give Git a spin on this project as it appears to be the emerging SCM of choice for open/public projects.

So what's it all about?

We are all familiar with includes, which work for both .as and .mxml files. This supports the code-behind style, which is a very useful separation mechanism when dealing with complex UI logic or copious event handler code. However, as a mechanism it is pretty stupid, relying only on assumption that internal dependencies (e.g. property existence) are satisfied. Of course, one can declare interfaces in .mxml and implement them in .as code-behind; I suppose this is the standard approach. The syntactical interface declaration (think: compiler) here also serves to declare (the availability of) any relevant behaviour (think: application feature) [Mixins are not necessarily or typically used this way, to add application features, but it is nonetheless the theme for my initial work]. However, firstly, the interface has to be defined and secondly the include is a waste full source include [Ok, it's debatable the real impact of this on binary size and performance blah blah blah... but from a idealist pov... it's not ideal]. I have found with this new approach to implementing mixins, you can achieve complete separation of responsibility e.g. keeping whatever it is your components are primarily supposed to do, from the behaviour implementation of the mixin. The state required for the mixin to function can be managed internally, negating the need for any interface definitions, declarations or implementations. And because the mixin is not used via a source include, there is only one compiled instance of the code in the binary. Application of the mixin is achieved through normal object-instantiation, not source inclusion everywhere the mixin behaviour is required. Another advantage of this new approach is that you do not need access to any source code; you do not need to re-write or extend some existing class in order to bolt on your desired behaviour. I will blog soon on how all this can be achieved. For now, have a look at an example of what the end result looks like; check out my Drag'n'Drop Mixin showcase. Cheers, q(^_^)p

Friday, February 13, 2009

Darren on Flex: Does Flex Have Serial Version Ids?

... And if it does, why don't they use them?

I came across this weird bug (see below) ages ago, that is ~6-8months, when trying to implement some custom drag'n'drop behaviour in a modular application. I had no flipping clue what it was going on about, threw my hands up in disgust and frustration and just shelved the whole thing (actually had to go earn my pay). I just recently came back to the drag'n'drop thing, developing in a singular app style. On completing what I set out to achieve (well, making satisfactory progress, [blog to follow]), I decided to revisit this bug. I found a work-around on Adobe's JIRA site but was confused by all the chatter. I Googled a bit more and found Greg Jessup's blog, where he posted the workaround some months earlier. With Greg's clear post, it was easy for me to rationalise this bug, such that I no-longer believe it is a bug... or rather not the WTF-kind. I categorize it now as a matter of some runtime-binary-compatibility issue, serializationy thingy. Hence why loading the classes in the Application (thus sharing the binary amongst the modules) solves the problem. I believe in the Java world, this is the kind of thing a serial-version-id is used to guard against, no? Anyway, cheers Greg.