New Domain: gorillajawn.com

Posted in Jon Rose on June 7th, 2009 by jonr

jonr originally posted this on Jon Rose's Blog.

I thought it was time for a less geeky blog domain.  I assume most people do not pay much attention to the domain name when visiting a blog anyway, but I have had gorillajawn.com for a while now, and thought it was time to put it to use.  For those who care, the new domain comes from a Gorillaz song, ‘November Has Come.’  In the song, “Jawn” is pronounced like “John.”   So, I thought this was a good fit…

Also, my old domain, ectropic.com, still works along with the old feeds.

Inkscape SVG to Degrafa Path

Posted in Justin Shacklette on June 3rd, 2009 by admin

admin originally posted this on Saturnboy.

Going from SVG data to a Degrafa Path couldn’t be easier: just copy & paste. You can watch this video tutorial or you can check out this demo.

But there is one trick for Inkscape: even though the coordinate origin on the Inkscape document is the normal cartesian origin in the bottom left and the y-axis points up, the SVG output always uses the upper left corner of the document as the origin and the y-axis points down (per the SVG Spec, § 7.3).

To demonstrate, I created a new document in Inkscape, set my dimensions to 500 x 500, and placed a simple path (which happens to be a square) in the upper left corner:

square

You can see by the rulers in Inkscape that the square’s origin is at (0,500).

If we save our square and examine the SVG output, we see:

<svg ...>
  <g ...>
    <path d="M 0,0 L 100,0 L 100,100 L 0,100 L 0,0 z" />
  </g>
</svg>

If we ignore everything in the file except the relevant path data, we can see the very first path command is M 0,0 which is path-speak for move to (0,0). This is exactly as expected from the SVG spec: upper left is the coordinate origin. The cartesian origin in Inkscape is bogus!

Next, we can just copy the path data from the SVG file and paste it into the data attribute of a Degrafa Path component.

<Degrafa:Path data="M 0,0 L 100,0 L 100,100 L 0,100 L 0,0 z">
    <Degrafa:fill>
        <Degrafa:SolidFill color="#EECCEE" />
    </Degrafa:fill>
    <Degrafa:stroke>
        <Degrafa:SolidStroke color="#FF00FF" weight="3" />
    </Degrafa:stroke>
</Degrafa:Path>

Give it a fill color and a stroke color, and we get a pretty purple square. Now I know my Degrafa Path component will have a square in the upper left, because I know my square was in the upper left in Inkscape. Nice and easy.

Files

Community Review: FlexMonkey (Flex UI Testing Tool)

Posted in FlexMonkey on June 3rd, 2009 by jonr

jonr originally posted this on FlexMonkey :: Flex UI Testing Tool.

Marcin Zreda provided a review on FlexMonkey version 0.8 in a recent blog entry.  He hit on some the key items that set FlexMonkey apart from other Flex testing tools.  A main benefit is that it generates ActionScript code.  Thus, there is nothing new for Flex developers to learn, such as the Ruby programming language with other testing tools.

FlexMonkey generates test scripts in Action Script. It gives us great opportunities to continue work by the test developers, and indeed very easy to integrate with the Continuous Integration tools because the test scripts are the FlexUnit format.

His summary concluded that FlexMonkey is a serious tool in the Flex testing space:

Looking at the whole family of automated GUI testing tools, FlexMonkey certainly deserves a honorable mention – is a complete tool, although version 0.8. Using Continuous Integration and the code repository can quickly combine to create solution very similar to RIATest or other profesional and expensive software.

You can read the full review here: http://www.testandtry.com/2009/04/07/flexmonkey-flex-test-automation-tool-review.

FlexMonkey is built and open sourced by Gorilla Logic, Inc.

In a Perfect World….

Posted in Stu Stern on June 1st, 2009 by Stu Stern

Stu Stern originally posted this on Big Gorilla - Stu Stern's Blog.

In a perfect world, we could focus solely on implementing functional requirements and not have to do anything explicitly to deal with non-functional constraints such as keeping shared resources from becoming bottlenecks or contending with bandwidth limitations. It can be instructive to consider what an application would look like if there were no physical constraints. Imagine if we lived in a world with infinite memory, infinite processing capacity, unlimited bandwidth, zero down-time, and interesting television shows (Imagine really hard). In such a world, queries are blindingly fast , there is no limit to how often we interact with the back-end, and we can can constantly exchange enormous amounts of data if we need to. With such a platform, we are free to develop our application without any consideration of physical constraints. Each view can refresh the data it is displaying nearly instantaneously, and we can immediately transmit changes to the back-end, and immediately receive notifications of any errors encountered.

In such an environment, the need for a great many design constraints is removed, although not completely eliminated. Even with physical constraints removed, logical constraints remain. Still, removing the physical constraints certainly simplifies software construction by removing the need to manage limited resources efficiently. Of course, in the real world of enterprise applications, there is no such environment, but not every physical or logical constraint is an issue for every application. Low volume applications or those with very small and simple data requirements can often behave almost as if they were executing in the (near-)perfect world. Consider for example an application that allows a user to update their name, address, and credit card information. As soon as the user logs in, you can easily retrieve such a small volume of data immediately, and you wouldn't have to contend with the user's name and address being changed by someone else simulataneously. You can then allow the user to update any of the returned data, updating their name and address, deleting some credit cards and adding others. If there are few simultaneous users, we can transmit each change immediately to the server where we immediately run required edit checks against it and report any errors encountered back to the client for communication to the user via the UI. Such an approach allows us to write an application in what is arguably the most “natural” way, ie, the simplest way. Physical constraints, on the other hand, force us to commit "unnatural acts", ie, they force us to write code that is more complex than it needs to be from a purely logical perspective.

With RIA's, there are a few physical constraints which are fundamental at this point in time. The client application is a separate process (on a unique platform), and all communication with the server-side must be accomplished by messaging. It is this constraint, more than anything else, that distinguishes ERIA architecture from web applications, two-tier client server applications, or one-tier local applications. And speaking of one-tier applications, it is worth noting that virtually no enterprise application allows for the data to be persisted entirely on the client box. It is virtually always the case that we cannot rely on the client itself for safe storage of business records, and there are typically large amounts of non-client-specific data (such as a product catalog) that are usually too large to make client-side distribution practical.

Another constraint is the almost universal requirement that persistence be provided by a non-object-oriented datastore, typically a relational database. There is of course a fundamental impedance mismatch between object- and a relational-centric data structures that is at the heart of many unnatural programming acts, and although there have been many variations on “object databases” over the years, relational databases continue to dominate for good reasons we’ll explore in some depth another time. In a perfect world, queries would return graphs of objects rather than lists of rows. Fortunately, persistence management frameworks such as Hibernate automate a good deal of the acrobatics involved in object-relational mapping, but unfortunately are not (yet?) fully transparent to the application developer, requiring varying amounts of explicit coding.

Coding in the real world requires more effort than coding in the perfect world because we need to add code to work around physical constraints. It would seem to be self-evident that since it takes more effort to add more code, you should only do so when there is an actual requirement to do so. In other words, the default architecture for any ERIA is essentially the simple one described above. We retrieve all the data up-front. Operate on the data as necessary. And send edits to the back-end as they occur. In pondering each of the questions posed above, the default answer in each case is this straight-forward, perfect world architecture since it requires the least effort to build. In each case however it is also necessary to consider how physical constraints can force the undertaking of more complicated strategies, but again, it should be emphasized that in the absence of any such physical constraints, the simplicity of the perfect world approach is the way to go.

Article: What’s New in Flex 4?

Posted in Jon Rose on June 1st, 2009 by jonr

jonr originally posted this on Jon Rose's Blog.

In addition, to my Top 10 Changes in Flex 4 article, my colleague Justin Shacklette and I published an article on DZone titled, What’s New in Flex 4? The article gives those new to Flex a tour of the most important changes that are coming with Flex 4, including a review of the Spark component architecture.

Degrafa Video Player, Part 2

Posted in Justin Shacklette on June 1st, 2009 by admin

admin originally posted this on Saturnboy.

The plan is simple, take the nice Degrafa-skinned components from Part 1 and assemble them into a video player powered by the OvpNetStream class from the Open Video Player project.

Design

I knew right away that the design was not going to have any right angles, but I also didn’t want to go with rounded rectangles everywhere. Modern TVs tend to have a lot of soft rounded edges, so I decided to go with a more vintage look. So I fired up Inkscape and got to work:

tv

Implementing the video player design above in Degrafa, the cabinet mapped to a RoundedRectangle, and the screen & antenna became Paths. You can read more about about translating SVG to Degrafa in my Inkscape SVG to Degrafa Path article. But for now, let’s focus on the resulting Degrafa code:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
        xmlns:mx="http://www.adobe.com/2006/mxml"
        xmlns:Degrafa="http://www.degrafa.com/2007"
        layout="absolute">
 
    <Degrafa:GeometryComposition graphicsTarget="{[box]}">
        <!-- Antenna -->
        <Degrafa:Path data="...path data...">
            <Degrafa:transform>
                <Degrafa:TranslateTransform x="15" />
            </Degrafa:transform>
        </Degrafa:Path>
 
        <!-- TV cabinet -->
        <Degrafa:RoundedRectangle y="144" width="350" height="300"
                cornerRadius="20" />
 
        <Degrafa:fill>
            <Degrafa:SolidFill color="#333333" />
        </Degrafa:fill>
        <Degrafa:stroke>
            <Degrafa:SolidStroke color="#FF00FF" weight="4" alpha="0.4" />
        </Degrafa:stroke>
    </Degrafa:GeometryComposition>
 
    <!-- TV Screen -->
    <Degrafa:GeometryComposition graphicsTarget="{[tvscreen]}">
        <Degrafa:Path data="...path data...">
            <Degrafa:fill>
                <Degrafa:SolidFill color="#FF99FF" />
            </Degrafa:fill>
            <Degrafa:stroke>
                <Degrafa:SolidStroke color="#FF00FF" weight="2" alpha="0.4" />
            </Degrafa:stroke>
            <Degrafa:filters>
                <mx:GlowFilter color="#EEEEEE" alpha="0.2" blurX="16" blurY="16" />
            </Degrafa:filters>
        </Degrafa:Path>
    </Degrafa:GeometryComposition>
 
    <mx:Canvas width="350" height="444"
            horizontalCenter="0" verticalCenter="0">
        <mx:Canvas id="box" />
        <mx:Canvas x="50" y="174" id="tvscreen" />
    </mx:Canvas>
</mx:Application>

I ended up using a pair of GeometryCompositions to wrap my three shapes to help keep my fills, strokes, and filters organized. It made sense to do it this way, but I won’t claim it’s the best way. Throw the control bar on below the TV screen, and the design is done.

Backend

The backend is build on the OvpNetStream class provided by the Open Video Player project. OvpNetStream extends NetStream and smooths out some of the rough edges as I discussed previously. Basically, it provides a sane interface (no need to construct a dynamic object with function callbacks) and useful events (like metadata and progress events).

For this demo, we simply instantiate OvpNetStream on creationComplete and wire up all the event handlers:

private function complete():void {
    nc = new OvpConnection();
    nc.addEventListener(OvpEvent.ERROR, errorHandler);
    nc.addEventListener(NetStatusEvent.NET_STATUS, connStatusHandler);
    nc.connect(null);
 
    ns = new OvpNetStream(nc);
    ns.addEventListener(OvpEvent.ERROR, errorHandler);
    ns.addEventListener(NetStatusEvent.NET_STATUS, streamStatusHandler);
    ns.addEventListener(OvpEvent.NETSTREAM_METADATA, streamMetadataHandler);
    ns.addEventListener(OvpEvent.PROGRESS, streamProgressHandler);
    ns.addEventListener(OvpEvent.COMPLETE, streamCompleteHandler);
 
    vid = new Video();
    vid.attachNetStream(ns);
    vidContainer.addChild(vid);
}

The most interesting events are the metadata and progress events. The metadata event delivers the duration of the video and its size. The progress event arrives periodically (theoretically every 100ms by default, but in reality I see them come in just a couple of times per second) and delivers the current video time.

Control Bar

The control bar consists of three components: a play-pause button, a scrubber, and a volume slider. They were skinned using Degrafa in Part 1. In order to control video playback, we need to wire the control bar components to the instance of OvpNetStream created above.

Here are the event handlers for the three control bar components:

// PlayPause event handler
private function playPauseClick():void {
    if (first) {
        first = false;
        ns.play(filename);
    } else {
        ns.togglePause();
     }
}
 
// Scrub event handlers
private function scrubPress():void {
    ns.pause();
    playPause.selected = false;
}
private function scrubDrag():void {
    ns.seek(scrub.value);
}
private function scrubRelease():void {
    ns.togglePause();
    playPause.selected = true;
}
 
// Volume event handler
private function volumeChange():void {
    ns.volume = volume.value;
}

In the playPauseHandler(), the initial click calls play() which actually loads the video (and then starts playback), all subsequent clicks just toggle between play or pause. For the scrubber handlers, I chose to break them up into three separate steps: on mouse down pause the video, on mouse up restart playback, and on drag attempt to seek to the to the new time.

That’s it. Here is the resulting Degrafa-skinned video player (view source enabled):

Flash is required. Get it here!

Click Play to start playing Elephants Dream (which is the “world’s first open movie,” and pretty cool too). Right away you’ll notice some visual issues because the dimensions of the video are unknown until the metadata arrives. Also, scrubbing has some problems which I believe are related to cue points in progressive downloads. Lastly, I didn’t implement any indicators for buffering or download progress, so you’ll need to be patient. Since this is just a demo, I’ll have to leave fixing those bugs as an exercise for the reader.

Files