<?xml version="1.0" encoding="utf-8"?>
<feed version="0.3" xmlns="http://purl.org/atom/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="en">
<title>Chet Haase&apos;s Blog</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/chet/" />
<modified>2008-04-23T15:24:43Z</modified>
<tagline></tagline>
<id>tag:weblogs.java.net,2008:/blog/chet/81</id>
<generator url="http://www.movabletype.org/" version="3.01D">Movable Type</generator>
<copyright>Copyright (c) 2008, chet</copyright>
<entry>
<title>Not Dead Yet</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/chet/archive/2008/04/not_dead_yet.html" />
<modified>2008-04-23T15:24:43Z</modified>
<issued>2008-04-22T18:32:08Z</issued>
<id>tag:weblogs.java.net,2008:/blog/chet/81.9589</id>
<created>2008-04-22T18:32:08Z</created>
<summary type="text/plain">Join Romain and I for another Filthy Rich Clients session at JavaOne this year.</summary>
<author>
<name>chet</name>


</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/chet/">
<![CDATA[	<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
	</script>
	<script type="text/javascript">
  var urchinCalled;
  if (!urchinCalled) {
	_uacct = "UA-1223303-2";
        urchinCalled = true;
        urchinTracker();
  }
	</script>
	<script src="http://weblogs.java.net/blog/chet/archive/javanetblogbar.js" type="text/javascript"></script>
<p><a href="http://www.curious-creature.org">Romain</a> and I will be returning to JavaOne this year to give another talk this year. We thought about presenting on horticulture, or the effect of air travel on the Amazon rain forest, but in the end we decided at random to talk about this topic: <a href="https://www28.cplan.com/cc191/session_details.jsp?isid=296611&amp;ilocation_id=191-1&amp;ilanguage=english"><em>Filthy Rich Clients: Filthier, Richer, Clientier</em></a>. And though it was tempting to just present stuff we'd already written (with 550 pages of material in the book, there's a lot to, well, steal for presentations), we thought it would be more fun and to do new stuff. Who needs sleep? We hope you can make it to the session.<strong></strong></p>
<p>For anyone that signed up for the session already, we hope you got word that the conference has shuffled us out of our original slot on Tuesday and put us on Thursday afternoon instead (4:10 - 5:10 pm). Maybe they just realized that everyone enjoys pre-enrolling for sessions so much that they figured you'd want another chance to log in and see how that change affected your schedule. And if you didn't pre-register for the session yet, you might want to do so; I've heard that the room is filling up (It's not clear why - maybe it was the &quot;free money!&quot; mention in the abstract. Or maybe it's Romain's groupies. Again.).</p>
<p>There's other stuff happening as well. For one thing, there's an author signing for our book. Maybe someone can explain to me why you actually want us to deface your book. It's a nice book,  clean and professional looking, and you want us to write in it? I understand having a famous author sign a book they wrote; heck, it'll be worth more when they're dead. But the authors of <a href="http://filthyrichclients.org"><em>Filthy Rich Clients</em></a>? The only thing worth more when I'm dead will be my life insurance policy. Anyway, we'll be there at the bookstore, signing anything you put in front of us except a blank check.</p>
<p>For other happenings that week, check out my <a href="http://graphics-geek.blogspot.com/2008/04/javaone-too.html">other blog</a>.</p>
]]>

</content>
</entry>
<entry>
<title>Crystal Methodology</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/chet/archive/2008/01/crystal_methodo.html" />
<modified>2008-01-17T21:20:10Z</modified>
<issued>2008-01-17T21:19:58Z</issued>
<id>tag:weblogs.java.net,2008:/blog/chet/81.9012</id>
<created>2008-01-17T21:19:58Z</created>
<summary type="text/plain">Process, process, process.  Process.</summary>
<author>
<name>chet</name>


</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/chet/">
<![CDATA[	<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
	</script>
	<script type="text/javascript">
  var urchinCalled;
  if (!urchinCalled) {
	_uacct = "UA-1223303-2";
        urchinCalled = true;
        urchinTracker();
  }
	</script>
	<script src="http://weblogs.java.net/blog/chet/archive/javanetblogbar.js" type="text/javascript"></script>
        <p>
            Not only am I a huge fan of <a href="http://weblogs.java.net/blog/chet/archive/2003/08/patterns_shmatt.html">
                software design patterns</a>, I'm also strongly supportive of <em>process</em>
            in software.
            Process makes us strong. Process enables us to achieve highly metric-driven
            quality
            levels. Process allows us to attend meetings throughout every day, ensuring that
            any coding time we get will be that much more intense because it is necessarily
            so short and focused. And finally, process allows us to draw pretty charts and graphs on
            endless presentations.</p>
        <p>
            Or, as I like to say it every morning when I wake up, "Software <em>Is</em> Process."
            For without the process, where would software engineers be but in their offices,
            cranking away code, pretending to be productive?</p>
            <p>
                Now that people have had time to understand and incorporate the important patterns
                I discussed in my earlier <a href="http://weblogs.java.net/blog/chet/archive/2007/10/male_pattern_bo.html">
                    Male Pattern Boldness</a> article, it seems high time to tackle the larger topic of
                Software Processeseses. The field of Software Methodology is rife with theories,
                names, buzzwords, and descriptions that improve our tawdry geek lives constantly by letting
                us focus on that which makes us most productive: studying and then trying to
                implement completely new software processes to attempt the same job that we could have
                been actually doing in the meantime.</p>
        <h2>
            Hysteresis</h2>
        <p>
            First, here is a historical perspective. Traditional software implementation was a rather
            simple and straightforward process, resembling something like the following:</p>
            <p style="text-align: center">
            <img alt="Process1.gif" src="http://weblogs.java.net/blog/chet/images/Process1.gif" width="506" height="82" /><br />
                <strong>Figure 1</strong>: Comprehensible, and therefore wrong, software process.</p>
        <p>
            But this process was flawed by its inherent simplicity; if everyone could understand
            and follow it, what hope did the industry have in creating more meetings and process
            documentation? Changes were suggested for this methodology, resulting in more comprehensive
            models like this one:</p>
            <p style="text-align: center">
            <img alt="Process2.gif" src="http://weblogs.java.net/blog/chet/images/Process2.gif" width="506" height="274" /><br />
                <strong>Figure 2</strong>: More complicated, and therefore better, software process.</p>
        <p>
            Eventually, some rogue elements of the community came up with a different process
            model, based on fundamental programming philosophies:</p>
            <p style="text-align: center">
            <img alt="Process3.gif" src="http://weblogs.java.net/blog/chet/images/Process3.gif" width="525" height="208" /><br />
                <strong>Figure 3</strong>: Simplified Software Process (SSP) model. Pretty dumb. Incredibly popular.
            </p>
            <p>
                But the field has been somewhat quiet lately, leading to more coding than is really
                good for us, so I feel motivated to introduce some of my favorite new process models
                into the community. There are obvivously more than I can cover in a simple article like
                this, probably deserving an entire bookcase of unread tomes, but these will
                have to do for now as I have to go brainstorm with my team in an offsite about how
                we can be more effective (this week's task is to come up with a mission statement).</p>
        <h3>
            Scum</h3>
            <blockquote>
                In the <a href="http://en.wikipedia.org/wiki/Scrum_%28development%29">Scrum</a>
                development model, the focus is on short iterations and constant communication.
                The Scum model, however, focuses on the individual. In particular, each
                engineer works completely on his or her own, producing code at an alarming rate.
                Changes are integrated and merged willy-nilly, causing untold breakage due to the complete
                lack of communication. At each fault, the offending code, putback, and engineer
                are indentified as <em>scum</em> and are tossed out of the project (this step is
                called "Hack-n-rack"). The resulting code
                and team are thereby better over time, having weaned out the weak members through
                natural selection.</blockquote>
            <blockquote>
                As it's inventor, Dr. Feen Bookle, PhD, Mrs, QED, JRE, said at its unveiling at
                the Conference On Terribly Important Academic Philosophies and Theories on Software
                Process Methodology Discoveries (CTEAPTSPMD), "Scum will always float to the top.
                Skim it off and you've got just the juicy bits left. Plus the bottom-feeders."</blockquote>
        <h3>Fragile Programming</h3>
            <blockquote>
                As I mentioned in my <a href="http://weblogs.java.net/blog/chet/archive/2007/10/male_pattern_bo.html">
                    earlier article</a>, Fragile Programming is an important element of the <em>Delicate</em>
                software pattern. It is related to <a href="http://en.wikipedia.org/wiki/Agile_software_development">
                    Agile</a> programming, which is typified by small development cycles that are
                designed to meet the reality of constant requirements churn. But in the newer, and
                therefore better, Fragile methodology, each iteration is started from scratch
                based on only the latest requirements. Instead of building upon the existing code
                base, which has presumably attained some amount of stability and robustness through
                its existence and evolution, Fragile projects rewrite the entire project anew in
                each cycle, thus generating brand spanking new products that adhere more closely to the latest
                whim of the client. This process results in software that is tuned exactly to what
                the client asked for, and the resulting instability of the code base can thus be
                blamed directly on the client, allowing a convenient excuse for the failing
                development team.</blockquote>
        <h3>Conference Drive Development (CDD)</h3>
            <blockquote>
                This brave new methodology, suggested to me by <a href="http://headius.blogspot.com/">
                Charles Nutter</a>, looks like it has serious potential. As anyone who has
                ever developed software and demos for a conference before knows too well, there's
                nothing like a looming keynote or session deadline to enforce good coding standards,
                carefully thought-out APIs, and integrated feedback from the larger community. Developers
                typically end up at conferences with completely spec'd out products that only lack
                for a smattering of documentation before being released out onto the masses like
                white
                cat hair on a black sweater. It's
                just that whole "Quality" part of the release process that drags it down for the
                next couple of years and keeps it from being
                an instant product reality.</blockquote>
            <blockquote>
                With the increasing volume of conferences around the world, I see CDD as becoming
                more and more interesting. Products that hinge releases upon the mad rush of pre-conference
                development will be able to ship new versions every month, or even faster.
                Sure, they'll go out with bugs, no documentation, and a complete lack of testing,
                but the demos will rock!</blockquote>
        <h3>Rabid Application Development</h3>
            <blockquote>
                <a href="http://en.wikipedia.org/wiki/Rapid_application_development">Rapid Application
                    Development</a> helped move developers from the more stodgy
                development processes of earlier decades when people were dumber onto quicker models
                of development, based on fast prototyping work. <em>Rabid</em> Application Development takes this a step further. Instead of using prototypes
                as ideas to help with future, more stable work, the prototypes <em>are</em> the product,
                and are checked in as soon as they are complete, or in many cases, sooner. The key
                to Rabid Development is to keep the engineering team going at such a frenetic pace
                in coding and checking in code that nobody, including the client, ever realizes
                what a complete load of crap they've produced. This model is used throughout most
                university CS courses and has become the default process basis for all homework assignments. It is also
                the mainstay of software startups everywhere.</blockquote>
            <h3>
                Cliff</h3>
            <blockquote>
                Developed as a response to the <a href="http://en.wikipedia.org/wiki/Waterfall_model">Waterfall</a>
                model, where software goes through various stages of development during its life
                cycle, the Cliff model leaps suddenly from the starting point (known as the <em>Hairbrained
                    Idea</em>) to the end (known as the <em>Product</em>, but informally referred to by Cliff teams
                as the <em>Corpse</em>). These projects are generally executed overnight with several pots
                of coffee by developers with no social lives. They start from an idea in a chat message during a World of Warcraft session and result in the engineers checking in the Corpse
                by the start of work the next morning.</blockquote>
            <blockquote>
                No output of the Cliff model has ever been useable outside of negative case studies,
                but interest in this approach persists by those engineers still lacking in better
                things to do at 2 AM.</blockquote>
            <h3>
                Oops</h3>
            <blockquote>
                Related to <a href="http://en.wikipedia.org/wiki/Object_oriented_programming">
                Object Oriented Programming</a> (OOP) methodologies, the Oops system seeks to develop
                reusuable objects, but never quite makes it. Previous components are
                never exactly
                what they need to be, thus requiring that the functionality be rewritten
                from scratch, resulting in a general "Oops!" exclamation from the teams involved.
                But as all engineers know, and all managers hate, it's always more fun writing things
                from scratch anyway.
                The Oops methodology is the one most favored by all programmers.</blockquote>
            <h3>
                Clean Your Room (CYR)</h3>
            <blockquote>
                This methodology comes as a response to the <a href="http://en.wikipedia.org/wiki/Cleanroom_Software_Engineering">
                    Cleanroom Software
                Engineering</a> process, which strives to produce software
                whose quality can be certified. <em>Clean Your Room</em>, on the other hand, takes a different
                tack,
                basing its philosophy upon the teenage kid tenet:
                "Why should I clean my room when it's just going to get dirty again?" In this process,
                the focus is upon implementing cool, new features (called <em>Wall Posters</em> after the typical
                decorations in
                most teenager bedrooms) and not on tests, documentation, or bug-fixes.
                The belief with these other traditional elements of software products is
                that as the software changes, tests would be obsoleted, documentation would have
                to be rewritten, and new bugs would be introduced. So what's the point in doing
                the work twice? All CYR
                projects are run under the theory that eventually,
                when the product is completely done, the other non-coding aspects of the product will eventually
                be seen to (hopefully
                by someone else). Since no CYR project has ever reached completion,
                this has yet to be proven in practice.</blockquote>
            <h3>
                Testosterone-Driven Development</h3>
            <blockquote>
                Like its namesake <a href="http://en.wikipedia.org/wiki/Test_driven_development">Test-driven
                    Development</a>, which is known for the requirement of engineers writing tests
                before code, Testosterone-driven Development focuses on testing first. But it does
                so in an an extremely aggressive manner, requiring every engineer to produce entire test
                suites, test frameworks, and test scripting languages for every line of product
                code written, including whitespace and comments. Engineers violating this contract
                are taken out back where they have the crap kicked out of them. Any code found to have bugs
                not caught by tests results in the offending engineer having to go three
                rounds with
                the project manager (with the engineer being handcuffed and blindfolded during the
                match). Finally, any bug found in tests will result in the engineer's body never being
                found again.</blockquote>
            <blockquote>
                Expectations are high from this newcomer to the field, although to date none of
                the products using this process has left any survivors.</blockquote>
            <p>
                I realize that the above list is quite a small sampling of the many wonderful methodologies
                which are possible. But I hope you will try at least some, or maybe even all, of
                these out in your team, throwing the entire project into disarray every couple of
                years while you reinvent everything. If you find either success
                or complete abject failure in your attempts, I encourage you to write a paper, speak
                at conferences, and publish books on the topic. Then form a consulting company that
                helps other development teams try to adopt the same methdologies.</p>
                <p>
            Software products are a journey. They aren't just about the code you see
            at the end; they're about the path taken to get there. And the paths not taken.
            And the signs on the road. And the maps used. And the gas station attendants asked
            for directions when you got lost. And the hikes through the wilderness when you
            ran out of gas. And the ceaseless talk radio that your parents played while you
            got carsick in the back all over your sister. Process is the car that gets you there;
            you just need to pick the right one, pay too much for it, and then build it from
            scratch first.</p>]]>

</content>
</entry>
<entry>
<title>Scene Graph: Demo-licious</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/chet/archive/2008/01/scene_graph_dem.html" />
<modified>2008-01-17T18:28:22Z</modified>
<issued>2008-01-17T18:28:09Z</issued>
<id>tag:weblogs.java.net,2008:/blog/chet/81.9010</id>
<created>2008-01-17T18:28:09Z</created>
<summary type="text/plain">The Scene Graph team has been writing demo applications for some time - now we&apos;ve finally published them.</summary>
<author>
<name>chet</name>


</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/chet/">
<![CDATA[	<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
	</script>
	<script type="text/javascript">
  var urchinCalled;
  if (!urchinCalled) {
	_uacct = "UA-1223303-2";
        urchinCalled = true;
        urchinTracker();
  }
	</script>
	<script src="http://weblogs.java.net/blog/chet/archive/javanetblogbar.js" type="text/javascript"></script>
    <p>
        In the dark ages, before the <a href="https://scenegraph.dev.java.net/">Scene Graph</a>
        project was public, development on the library was coupled with development of demo
        applications. These demos were written for various reasons: to test new functionality,
        to get a feel for the API and development experience, to have benchmarks for performance
        tuning, and to have stuff to show when we talked about it at <a href="http://javapolis.com">
            conferences</a>.</p>
    <p>
        When we made the Scene Graph library public, we also wanted to make our demo applications
        public. But there was one big problem; unlike the library itself, we hadn't written
        those applications with the public, or even anyone but ourselves, in mind. And publishing
        code that you haven't actually sanity-checked can be unwise. So we
        posted the library with just the Nodes demo (quickly cleaned up for the occasion, like putting a tuxedo
        on a homeless guy),
        and the intention of going back to get the other demos in a publishable state.</p>
    <p>
        Now, a month later, we think we're there; we've created a <a href="https://scenegraph-demos.dev.java.net/">
            new project</a> on java.net to host all of our public demos, including the Nodes
        demo already published as well as the jPhone demo discussed in <a href="http://weblogs.java.net/blog/chet/archive/2008/01/write_a_phony_a.html">
            my previous blog entry</a>. You can go to that project, run the demos, see the
        code, sync up to the source base, and play around with all of them.</p>
    <p>
        Feedback (on the demos or the Scene Graph in general) should use the forums and
        aliases on the <a href="https://scenegraph.dev.java.net/">Scene Graph</a> project,
        not the demos project (at least until we figure out how to disable those elements
        on that project). It's helpful to funnel all of the feedback through one
        channel.</p>
    <p>
        So what are you reading this for? Go to the <a href="https://scenegraph-demos.dev.java.net/">
            scenegraph-demos</a> project and enjoy the new stuff. It's demo-licious.</p>
]]>

</content>
</entry>
<entry>
<title>Write a Phony Application ... Or Dial Trying</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/chet/archive/2008/01/write_a_phony_a.html" />
<modified>2008-01-18T00:01:01Z</modified>
<issued>2008-01-16T21:29:22Z</issued>
<id>tag:weblogs.java.net,2008:/blog/chet/81.9003</id>
<created>2008-01-16T21:29:22Z</created>
<summary type="text/plain">A dissection of a new Scene Graph demo, JPhone.</summary>
<author>
<name>chet</name>


</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/chet/">
<![CDATA[	<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
	</script>
	<script type="text/javascript">
  var urchinCalled;
  if (!urchinCalled) {
	_uacct = "UA-1223303-2";
        urchinCalled = true;
        urchinTracker();
  }
	</script>
	<script src="http://weblogs.java.net/blog/chet/archive/javanetblogbar.js" type="text/javascript"></script>
    <p>
        A few weeks ago, in a quest for more performance benchmarks, the scene graph team
        asked for a demo that was representative of some of the graphics and animations that
        might be typical in a consumer-oriented application.</p>
    <p>
        I had run across an interesting video on the Apple site recently, <a href="http://www.apple.com/iphone/gettingstarted/guidedtour/">
            iPhone: A guided tour</a>. The device in the video had ideas of what we were looking for; fades,
        moves, scales, transitions... all the whizzy animations that consumers love. So
        I took a whack at doing something similar with the scene graph.</p>
        <p>
        Introducing: JPhone:</p>
        <p>
        <a href="http://download.java.net/javadesktop/scenario/demos/jphone-JPhone.jnlp"><img alt="jPhoneLg.png" src="http://weblogs.java.net/blog/chet/images/jPhoneLg.png" width="328" height="514" /></a>
        </p>
    <p>
        Okay, so it's not really the same thing. For one thing, I just used some icons I
        had lying around which don't look as good at the large size required for this interface.
        I'd love to use the iPhone icons instead, but I'm still waiting for the Apple lawyers
        to call me back. And waiting. And waiting. (Steve?)</p>
    <p>
        Also, I guess I have to admit it: the jPhone demo is not a phone. Even if
        you pick up your monitor and hold it next to your ear, all you'll hear is the sound
        of your brain screaming in pain from the pixel radiation. (And the ocean. Isn't it
        funny how you can always hear the ocean? Or maybe it's just sound waves.)
        But mimicking a phone
        wasn't the point; it was all about the user interface.</p>
    <p>
        Finally, it'll become obvious when you start to use it that, well, there are no
        'applications' behind the icons; it's just the same dummy screen that comes up again
        and again. But once more, my petty rationalization comes in handy; the demo was
        supposed to be about GUI animations, not actual functionality.</p>
    <p>
        But hey, <em>It's A Demo!</em></p>
    <p>
        Anyway, on with the article. Note that my discussion below is all about the jPhone
        demo. I don't actually know how things operate under the hood on that phone thingie
        from Apple; all I know I learned from watching that video. But I do know how the
        jPhone demo works, so I'll stick to that.</p>
    <h2>
        The GUI: Main menu, tray menu, and applications</h2>
    <p>
        There are three different GUI areas in the display, used at different times. What
        I call the "main menu" is the grid of icons arrayed out across the first screen,
        starting at the top. Each of these icons accesses a different application (each
        of which looks uncannily similar in JPhone) when clicked. The "tray menu" at the bottom has four additional icons, which are much the same as the
        icons in the main menu, but for common functionality that the user might want to access more frequently.
        Finally, the "application" screens are those displays that come
        up after the user clicks an icon. For example, when the user clicks on the Calculator
        button, they probably expect a calculator application screen to become active.</p>
    <h3>
        Main Menu</h3>
    <p>
        The main menu of the application consists of a grid of icons, four columns wide.
        The menu is created in the cleverly-named <code>createMenu()</code> method.
    </p>
    <p>
        Each "icon" consists of both an image and a text caption. So for each icon object
        in the scene graph, we create an <code>SGGroup</code> to hold the children, 
        an <code>SGImage</code> to hold
        the image of the icon, and an <code>SGText</code> object to hold the caption.</p>
    <p>
        The group is created in a single line as follows:</p>
    <pre>        SGGroup imageAndCaption = new SGGroup(); </pre>
    <p>
        The image node takes a few more lines, as we need to scale the image appropriately
        and then set the image on the node:</p>
    <p>
        
        </p>
    <pre>        SGImage icon = new SGImage();
        try {
            BufferedImage originalImage =
                    ImageIO.read(getImageURL(mainMenuIcons[iconIndex]));
            BufferedImage iconImage = new BufferedImage(ICON_SIZE,
                            ICON_SIZE, BufferedImage.TYPE_INT_ARGB);
            Graphics2D gImage = iconImage.createGraphics();
            gImage.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                    RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            gImage.drawImage(originalImage, 0, 0, ICON_SIZE, ICON_SIZE,
                    null);
            gImage.dispose();
            icon.setImage(iconImage);
            imageAndCaption.add(icon);
        } catch (Exception e) {
            System.out.println("Error loading image: " + e);
        }</pre>
    (Note that our image scaling assumes that a one-step bilinear scale will give us
    sufficient quality, which it does in the case of up-scaling the smaller images we're
    using for icons. For a more general scaling solution that gives dependable quality and decent
    performance, check out <a href="http://weblogs.java.net/blog/campbell/">Chris
        Campbell</a>'s article on <a href="http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html">
        The Perils of Image.getScaledInstance()</a>).<p>
            The text node takes a few lines to set up the text rendering and location attributes
            appropriately:</p>
            <pre>        SGText textNode = new SGText();
        textNode.setText(iconCaptions[iconIndex]);
        textNode.setFont(captionFont);
        textNode.setFillPaint(Color.LIGHT_GRAY);
        textNode.setAntialiasingHint(RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        Rectangle2D rect = textNode.getBounds();
        textNode.setLocation(new Point2D.Double(
                (ICON_SIZE - rect.getWidth())/2, ICON_SIZE + 10));
        imageAndCaption.add(textNode);</pre>
    <p>
    To position each icon in the menu, and to allow the icon to be moved later when it
    animates, we create a transform node as the parent of the icon and add that node
        to the scene graph:
    </p>
    <pre>        SGTransform.Translate transformNode = SGTransform.createTranslation(xOffset, 
                yOffset, imageAndCaption);
        rootNode.add(transformNode);</pre>
    <h3>
        Tray Menu</h3>
    <p>
        The tray menu, initialized in the <code>createTray()</code> method, consists of just four icons at the bottom of the screen. These icons
        are mostly like the main menu icons, although they have a different background
        and the animation they undergo during transitions is different, so there are differences in their setup.</p>
    <p>
        First, the tray needs to be positioned on the screen, so the tray group needs an
        overall transform. Also, we will fade the tray in and out during transitions from
        and to the application screen, so the tray group also needs a filter node
        to handle fades. These nodes are set up as follows:</p>
        <pre>        final SGGroup trayGroup = new SGGroup();
        SGComposite opacityNode = new SGComposite();
        opacityNode.setOpacity(1f);
        SGTransform trayTransform = SGTransform.createTranslation(0, 
                SCREEN_H - (1.5 * ICON_SIZE), trayGroup);
        opacityNode.setChild(trayTransform);
        rootNode.add(opacityNode);</pre>
    <p>
        Next, we have an interesting background for the tray that consists of a basic gray
        gradient with a solid darker gray underneath the captions. We set this up with a
        couple of shape nodes and a transform node to position the darker area appropriately:</p>
        <pre>        // Set up the basic tray background
        SGShape trayBackground = new SGShape();
        trayBackground.setShape(new Rectangle(SCREEN_W, 
                (int)(ICON_SIZE * 1.5)));
        trayBackground.setMode(SGShape.Mode.FILL);
        trayBackground.setFillPaint(new GradientPaint(0f, 0f, Color.DARK_GRAY,
                0f, (float)(ICON_SIZE * 1.5), Color.LIGHT_GRAY));
        trayGroup.add(trayBackground);
        
        // Set up the darker background for the captions
        SGShape captionBackground = new SGShape();
        captionBackground.setShape(new Rectangle(SCREEN_W, 20));
        captionBackground.setMode(SGShape.Mode.FILL);
        captionBackground.setFillPaint(new GradientPaint(0f, 0f, Color.DARK_GRAY,
                0f, 10f, Color.GRAY));
        SGTransform captionBGTransform = SGTransform.createTranslation(0, 
                (1.5 * ICON_SIZE) - 22, captionBackground);
        trayGroup.add(captionBGTransform);</pre>
    <p>
        The icons themselves are set up just like those for the main menu, adding themselves
        to the <code>trayGroup</code> object created above; I'll skip the details since the code is similar
        to what we saw earlier for the main menu icons.</p>
    <h3>
        Application</h3>
    <p>
        The application objects, created in the <code>createApp()</code> method, are simply images. The
        only interesting part about them is the animation of scaling and fading in and out
        as they become active and inactive. We load and scale the application image just
        like we did for the icons in createMenu() above, so I won't show that code here.
        We then add filter nodes for opacity and for scaling, so that we can fade and scale
        the application screen during animations:</p>
        <pre>        // App screen is just an image, scaled/faded in when it becomes active
        final SGImage photo = new SGImage(); 
        // ... code to load/scale/set image removed for brevity ...
        photo.setVisible(false);
        SGComposite opacityNode = new SGComposite();
        opacityNode.setOpacity(0f);
        opacityNode.setChild(photo);
        AffineTransform fullScale = new AffineTransform();
        AffineTransform smallScale = 
                AffineTransform.getTranslateInstance(
                SCREEN_W/2, SCREEN_H/2);
        smallScale.scale(.1, .1);
        smallScale.translate(-SCREEN_W/2, -SCREEN_H/2);
        SGTransform scaleNode = SGTransform.createAffine(smallScale, opacityNode);
        fullScale = new AffineTransform();
        rootNode.add(scaleNode);</pre>
    <p>
        Note that the application node starts out invisible (because it is hidden until
        triggered by a mouse click on one of the menu icons), completely transparent (until
        it is faded in), and scaled to 10% of its true size (until it is scaled in during
        a later animation).</p>
    <h2>
        Animations</h2>
    <p>
        The objects set up above were necessary, but the fun part is really the animations
        that drive the application. The animations are all triggered based on user clicks. A click on
        the main menu icons will run animations on the main menu, the tray menu, and the
        application screen simultaneously. A click on the application screen will run
        all of the same animations - in reverse. Let's see how we set up and run these animations.
        There are two Timelines create to run these animations (recall from 
        <a href="http://weblogs.java.net/blog/chet/archive/2008/01/been_there_scen_1.html">an
            earlier blog entry</a> that Timeline is a convenient grouping mechanism for animations):</p>
        <pre>        Timeline menuOutTimeline = new Timeline();
        Timeline menuInTimeline = new Timeline();</pre>
    <h3>
        Main Menu Animation</h3>
    <p>
        The interesting part in the main menu animation is in trying to guess what's going
        on in the Apple video (and the iPhone interface). As an engineer, I would expect the icons to move in a linear
        fashion, sliding horizontally or vertically, perhaps the same every time, or maybe
        with the direction set based on which icon was clicked. In fact, one of the engineers
        on the team once rewrote my animation code to do just that, assuming that there
        was a bug in my code and I must have meant to have this straight-line animation instead of the effect I had implemented.
    </p>
    <p>
        But if you look closely at the video (or, heck, at that iPhone you have in your
        pocket), you'll see that the icons move in diagonal trajectories off of the screen,
        all shooting off in different directions. For example, here's a stop-action view
        captured from the video:</p>
    <p>
    <img alt="iPhoneAnim1crop.jpg" src="http://weblogs.java.net/blog/chet/images/iPhoneAnim1crop.jpg" width="202" height="383" />

    <img alt="iPhoneAnim2crop.jpg" src="http://weblogs.java.net/blog/chet/images/iPhoneAnim2crop.jpg" width="201" height="383" />

    <img alt="iPhoneAnim3crop.jpg" src="http://weblogs.java.net/blog/chet/images/iPhoneAnim3crop.jpg" width="201" height="387" />

    </p>
    <p>
    <img alt="iPhoneAnim4crop.jpg" src="http://weblogs.java.net/blog/chet/images/iPhoneAnim4crop.jpg" width="204" height="384" />

    <img alt="iPhoneAnim5crop.jpg" src="http://weblogs.java.net/blog/chet/images/iPhoneAnim5crop.jpg" width="201" height="382" />

    <img alt="iPhoneAnim6crop.jpg" src="http://weblogs.java.net/blog/chet/images/iPhoneAnim6crop.jpg" width="203" height="380" />

    </p>
    <p>
        Also, it looks the same every time, no
        matter which icon is clicked. I would then assume (and have implemented the code
        this way in jPhone) that the icons all shoot away from one central point on
        the screen. But that doesn't appear to be the case.</p>
    <p>
        Anyway, I think the animation for jPhone's main menu looks pretty good, if not exactly
        what they happen to do on that other device.</p>
    <p>
        The basic idea in jPhone is to calculate the movement vector based on some movement
        "center" (<code>xCenter, yCenter</code>) and the location of each icon (<code>xOffset, yOffset</code>):</p>
        <pre>        double xDir = xOffset - xCenter;
        double yDir = yOffset - yCenter;</pre>
    <p>
        We can then calculate the new offscreen position of the icon (<code>xOffscreen, yOffscreen</code>)
        using this direction vector (I won't show that code here for brevity, but it basically
        sets an offscreen value in one coordinate (x or y) and then calculates the other
        coordinate based on the direction vector).</p>
    <p>
        Finally, we can create an animation that will move the icon from its position in
        the main menu to this offscreen position as follows:</p>
        <pre>        Clip iconClip = Clip.create(MENU_OUT_TIME,
                transformNode, "translateX", xOffscreen);
        iconClip.addTarget(KeyFrames.create(
                new BeanProperty(transformNode, "translateY"), 
                yOffscreen));
        menuOutTimeline.schedule(iconClip);</pre>
    <p>
        The <code>transformNode</code> object being animated is the filter node in charge of the icon
        location, so this animation will alter the <code>translateX</code> and <code>translateY</code> properties
        of that object during the animation. Similarly, we create the opposite animation
        to move the icon back to its original location from where it's residing offscreen:</p>
        <pre>        iconClip = Clip.create(MENU_IN_TIME,
                transformNode, "translateX", xOffset);
        iconClip.addTarget(KeyFrames.create(
                new BeanProperty(transformNode, "translateY"), 
                yOffset));
        menuInTimeline.schedule(iconClip);</pre>
    <h3>
        Tray Menu Animation</h3>
    <p>
        Tray menu animation is simpler; we just fade the tray out and back in when applications
        become active or inactive. To fade the tray out, we create an animation on the <code>opacity</code>
        property of the <code>opacityNode</code> object that we created earlier:</p>
        <pre>        Clip fader = Clip.create((int)MENU_OUT_TIME, opacityNode, 
                "opacity", 1f, 0f);
        fader.addTarget(new TimingTargetAdapter() {
            public void end() {
                trayGroup.setVisible(false);
            }
        });
        menuOutTimeline.schedule(fader);</pre>
    <p>
        Note that we're actually doing two things here; we're fading out the node from opaque
        to completely transparent, and we're setting the visibility of the node to <code>false</code>
        when the animation ends. The visibility property of nodes controls whether the nodes
        process events or try to render themselves; since the node will be completely transparent
        when it is faded out completely, it doesn't make sense for it to participate in
        either events or rendering.</p>
    <p>
        When an application becomes inactive, we run the reverse animation on the tray menu
        to make it visible and fade it in:</p>
        <pre>        fader = Clip.create((int)MENU_IN_TIME, opacityNode, 
                "opacity", 0f, 1f);
        fader.addTarget(new TimingTargetAdapter() {
            public void begin() {
                trayGroup.setVisible(true);
            }
        });
        menuInTimeline.schedule(fader);</pre>
    <h3>
        Application Animation</h3>
    <p>
        Finally, we need to animate the application screen. These animations are similar
        to what we've seen before, although in this case we are both fading and scaling
        the application screen:</p>
        <pre>        final Timeline appAnims = new Timeline();
        Clip fader = Clip.create((int)MENU_OUT_TIME, opacityNode, 
                "opacity", .1f, 1f);
        Clip scaler = Clip.create((int)MENU_OUT_TIME, scaleNode, 
                "affine", smallScale, fullScale);
        appAnims.schedule(fader);
        appAnims.schedule(scaler);
        fader.addTarget(new TimingTargetAdapter() {
            public void begin() {
                photo.setVisible(true);
            }
        });</pre>
    <p>
        The application animation is also how we start tying the different animations and
        events together. First of all, we kick off the overall <code>menuOutTimeline</code> animation
        from the application animation by scheduling it as a dependent animation
        of the application's <code>fader Clip</code>, as follows:</p>
        <pre>        fader.addBeginAnimation(menuOutTimeline); </pre>
    <p>
        Next, we add an attribute to each icon that tells it which animation it is associated
        with:</p>
        <pre>        appIcon.putAttribute("startAnim", appAnims);</pre>
    <p>
        Finally, we add a mouse listener to each icon that will listen for clicks and start
        the animation appropriate for that icon:</p>
        <pre>        appIcon.addMouseListener(appStartListener);</pre>
    <p>
    where the mouse listener is defined to start the animation that we stored as an attribute
    on the icon in question:</p>
    <pre>        SGMouseListener appStartListener = new SGMouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e, SGNode n) {
                Animation a = (Animation) n.getAttribute("startAnim");
                a.start();
            }
        };</pre>
    <p>
        We do similarly for the reverse animation for the application (I'll skip that code
        for brevity and added surprise and excitement).</p>
    <h3>
        TransformComposer</h3>
    <p>
        <a href="http://weblogs.java.net/blog/campbell">Chris</a> might prefer that I not mention this detail, since the final API for the scene
        graph will hopefully make this step irrelevant, but for now the only way to animate
        transforms such as the moves and scales shown above is for the animation engine
        to know how to interpolate <code>AffineTransform</code> objects. It does not know how to do this
        by default (because, frankly, it's not typically the way you would want to interpolate
        between positions and orientations; it can produce unexpected results, thus the
        need for better functionality in the API eventually). So we need to add this capability
        to the application. We do this by creating a <code>TransformComposer</code> object
        that tells the system
        how to interpolate between AffineTransform objects, and we register the composer
        as follows:</p>
        <pre>        static {
            Composer.register(AffineTransform.class, TransformComposer.class);
        }</pre>
    <p>
        I won't go into the details of <code>TransformComposer</code> here, but see <a href="http://weblogs.java.net/blog/chet/archive/2008/01/been_there_scen.html">
            my earlier blog entry on the animation system</a> and the <code>Composer</code> 
            JavaDocs on the <a href="https://scenegraph.dev.java.net/">Scene Graph project site</a> 
            to understand more about <code>Composer</code>.
        Basically, a custom <code>Composer</code> simply converts between an arbitrary type and an array
        of double values, which the base <code>Composer</code> class then knows how to linearly interpolate
        between.</p>
    <h2>
        Runtime</h2>
    <p>
        That's mostly it. If you run the application and click on the icons you can
        see the fading, moving, and scaling animations all working together to show a nice,
        smooth transition between the menu and application screens.</p>
    <p>
        Of course, in demos enough is never enough. So we decided to put in one more element
        for fun.</p>
    <p>
        In the Apple video, you'll notice that many of the demos they show are run by this
        disembodied hand. It could be the Hand of God, but I don't think that Steve was
        in the video. Besides, the hand isn't wearing a black turtleneck.
        </p>
        <p>
        <img alt="iPhoneHand.jpg" src="http://weblogs.java.net/blog/chet/images/iPhoneHand.jpg" width="432" height="302" />
        </p>
        <p>
        It seemed like our demo needed an element like that, so we created
        the <code>handCursor</code> node.</p>
    <h3>
        Handy Cursor</h3>
    <p>
        Custom cursors are fairly easy in Java, but they are also fairly limited. In particular,
        your cursor image is limited to 32x32, which doesn't really give us the effect we
        were looking for. I want a hand, not a hand-shaped wart. We need a friggin' huge cursor.</p>
    <p>
        In a traditional Swing application, we could manage this using the glass pane, displaying
        an arbitrary image in that overlay on top of the application GUI. But the scene graph makes this
        even easier; we just need a shape node.</p>
    <p>
        First things first: we need to manage the real Swing cursor. Since we cannot use
        the actual cursor as our hand, we will instead make the real cursor invisible with
        the following code, so that if we can't make the cursor do what we really want,
        we can at least get it out of the way:</p>
        <pre>        BufferedImage emptyImage = new BufferedImage(32, 32,
                BufferedImage.TYPE_INT_ARGB);
        invisibleCursor = Toolkit.getDefaultToolkit().
                createCustomCursor(emptyImage, new Point(0, 0), "empty");</pre>
    <p>
        Next, we will create our <code>handCursor</code> object, parent it to the root node, and add
        it as a <code>MouseMotionListener</code> on the application as follows:</p>
        <pre>        handNode = new HandCursor(rootNode);
        addMouseMotionListener(handNode);</pre>
    <p>
        I won't show the entire <code>HandCursor</code> class (it's frankly not interesting enough), but
        the basics are as follows: First, we load the hand image and scale it to an appropriate
        size (using code similar to that shown earlier for the menu icons).
        Next, we create an <code>SGImage</code> node and a transform node (for moving it), and parent the transform node to the root node. We also make the shape invisible
        at first, since the hand cursor is not showing
        by default:</p>
        <pre>        handNode = new SGImage();
        handNode.setImage(largerHand);
        handNode.setVisible(false);
        handTransform = SGTransform.createTranslation(0, 0, handNode);
        rootNode.add(handTransform);</pre>
    <p>
        When the application frame detects that the key "h" has been typed, it makes the
        default cursor invisible and the hand cursor visible with the following:</p>
        <pre>        setCursor(invisibleCursor);
        handNode.setVisible(true);</pre>
    <p>
        Now, all we have to do is track the mouse
        position and display the hand node appropriately:</p>
        <pre>        public void mouseMoved(MouseEvent me) {
            mouseX = me.getX();
            mouseY = me.getY();
            handTransform.setTranslation(mouseX - 160, mouseY - 5);
        }</pre>
    <p>
        (where the hard-coded numbers in <code>setTranslation()</code> position the "hotspot" of the hand
        cursor at the tip of the index finger).</p>
    <h1>
        <code>return;</code></h1>
    <p>
        That's pretty much it. There's more code in JPhone, but I think I've covered
        all of the interesting scene graph-related pieces above. <a href="http://weblogs.java.net/blog/chet/archive/jphone-JPhone.jnlp">Play with it</a>, <a href="http://weblogs.java.net/blog/chet/archive/JPhone.java">check out
        the code</a>, and write a phony scene graph application of your own.</p>
        <p>
        <img alt="jPhoneAnim1.jpg" src="http://weblogs.java.net/blog/chet/images/jPhoneAnim1.jpg" width="164" height="257" />
        <img alt="jPhoneAnim2.jpg" src="http://weblogs.java.net/blog/chet/images/jPhoneAnim2.jpg" width="164" height="257" />
        <img alt="jPhoneAnim3.jpg" src="http://weblogs.java.net/blog/chet/archive/jPhoneAnim3.jpg" width="164" height="257" />
        <img alt="jPhoneAnim4.jpg" src="http://weblogs.java.net/blog/chet/images/jPhoneAnim4.jpg" width="164" height="257" />
        <img alt="jPhoneAnim5.jpg" src="http://weblogs.java.net/blog/chet/images/jPhoneAnim5.jpg" width="164" height="257" />
        </p>
    <h2>
        Related Information</h2>
    <p>
        <a href="http://download.java.net/javadesktop/scenario/demos/jphone-JPhone.jnlp">JPhone Demo</a>: a Java Web Start application</p>
    <p>
        <a href="http://weblogs.java.net/blog/chet/archive/JPhone.java">JPhone.java</a>: the source code for the main demo class</p>
    <p>
        <a href="http://weblogs.java.net/blog/chet/archive/TransformComposer.java">TransformComposer.java</a>: the source code for the custom composer helper class</p>
    <p>
        <a href="https://scenegraph-demos.dev.java.net/">Scene Graph Demos</a>: The project site for all of the Scene Graph demos posted by the
        team (including JPhone)</p>]]>

</content>
</entry>
<entry>
<title>Been There, Scene That: Part 2</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/chet/archive/2008/01/been_there_scen_1.html" />
<modified>2008-01-09T00:17:22Z</modified>
<issued>2008-01-09T00:17:13Z</issued>
<id>tag:weblogs.java.net,2008:/blog/chet/81.8948</id>
<created>2008-01-09T00:17:13Z</created>
<summary type="text/plain">And now, for the stunning conclusion of my previous blog entry. In this week&apos;s exciting climax, we&apos;ll go over some of the new, cool elements in the scene graph animation engine and end with a discussion of what it all means (life, animation - all of that).</summary>
<author>
<name>chet</name>


</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/chet/">
<![CDATA[	<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
	</script>
	<script type="text/javascript">
  var urchinCalled;
  if (!urchinCalled) {
	_uacct = "UA-1223303-2";
        urchinCalled = true;
        urchinTracker();
  }
	</script>
	<script src="http://weblogs.java.net/blog/chet/archive/javanetblogbar.js" type="text/javascript"></script>
        <p>
            <em>
        (This is the conclusion of a two-parter that was begun <a href="http://weblogs.java.net/blog/chet/archive/2008/01/been_there_scen.html">
                last week</a> and split in half
        for no particularly good reason. If you didn't read 
                <a href="http://weblogs.java.net/blog/chet/archive/2008/01/been_there_scen.html">last week's entry</a> yet, please
        do. I'll wait. ... Now, are you ready? Then let's get started.) </em>
        </p>
                <h2>New Stuff</h2>
        <p>Most of the changes between TimingFramework and the scene graph animation library
            are tweaks on existing 
            functionality, as described above. But there is also new functionality in the 
            scene graph animation engine. Some of it is functionality that
            we have wanted in 
            the TimingFramework for some time - we just happened to get around to it in this 
            animation engine first.</p>
        <h3>Timeline</h3>
        <p>The <code>Timeline</code> class is probably the biggest new thing since the
        Timing Framework. It adds a crucial missing piece of functionality from the 
            original library: the ability to group animations, schedule them in a 
            coordinated fashion, and use one, single heartbeat for all animations.</p>
        <h4><a href="http://www.imdb.com/title/tt0072431/">"Nice Grouping!"</a></h4>
        <p>The previous approach of daisy-chaining animations one-by-one with TimingTrigger 
            was quite useful for individual sequences of animations. And the new 
            <code>addBeginAnimation()/addEndAnimation()</code> methods of Clip enhance this capability 
            significantly. But it's still not what you want for larger systems with entire 
            groups of animations that need to be coordinated. Instead, you want some
            way to create groups of animations 
            that operate on a single timeline relative to
            each other and then schedule that group appropriately 
            with other animations or other
            animation groups. This functionality makes it much easier to build up 
            more complex and interdependent models of animations.</p>
        <p>Timeline enables this capability by allowing you to schedule animations on a given
            Timeline relative to when the Timeline itself starts. So, for example, if you 
            want to fire off animations a, b, and c 100, 200, and 300 ms after some even 
            occurs, then you can schedule these animations on a single Timeline and start 
            the Timeline when that event occurs:</p>
            <pre>            // Create the animation group
            Timeline timeline = new Timeline();
            timeline.schedule(a, 100);
            timeline.schedule(b, 200);
            timeline.schedule(c, 300);
            
            // Later, when the event occurs
            timeline.start();</pre>
        <h4><a href="http://en.wikipedia.org/wiki/Two_Hearts_Beat_As_One">"Two Hearts Beat as 
                One"</a></h4>
        <p>One of the biggest recurring constraints that I ran up against with the 
            TimingFramework was the fact that each Animator started its own Swing Timer by 
            default. You could change this behavior, with the late-addition class 
            <code>TimingSource</code>, but it wasn't a convenient way to get what you really
            wanted: a single timer for the whole system. You could also get a single-timer kind of behavior by adding multiple 
            TimingTargets to a single Animator, but this approach only works easily in 
            situations where you want similar timing and behavior characteristics from all 
            of these targets; for example, animations of different durations or interpolation
            are difficult to 
            synchronize in this way.</p>
        <p>What the system really needed was a single timing source that sent a heartbeat 
            pulse to all animations. Each animation could then turn that pulse into an 
            appropriate timing fraction, just as Animator does with its internal 
            Swing Timer events. But there are a couple of excellent reasons why the 
            single-pulse-generator model is superior to the multiple-Swing-Timer approach:</p>
        <ul>
            <li><strong>
                Synchronized animations</strong>: If you have several animations in the 
                system that are affecting the GUI, or are otherwise related in some way, 
                you probably want them all to receive their timing events at the same time 
                instead of at slightly different times because their internal Timers are 
                kicking off at different intervals. Coordinating
                rendering changes in the single GUI display is a Good Thing; each element animating
                separately from everything else around it could contribute to a more chaotic user
                experience.</li>
            <li>
                <strong>Resolution and frame rate</strong>: Anyone that worked through the gorey
                details in the Resolution section of chapter 12 of <a href="http://filthyrichclients.org">Filthy
                    Rich Clients</a> (or anyone that's 
                just worked closely with the Swing Timer) knows that the performance of that 
                Timer is often gated by constraints on the native platform. For example, on 
                Windows XP, the Swing Timer typically has an inter-event rate of about 16
                milliseconds. This is because that's the highest rate achievable by the native 
                low-resolution timer upon which the Swing Timer depends (through its use of 
                <code>Object.wait()</code>). This problem is compounded when there are several Timers firing 
                off at the same time, because the timing events are all gated by that 
                underlying <code>wait()</code> resolution, and cannot actually process the 
                <code>wait()</code>'s in parallel.<br/>
                For example, say you have one Animator that you'd like to set up with a resolution of 
                10 ms. On Windows XP, you'd actually get timing events at a resolution of 16 ms 
                instead. Now, suppose you create a second Animator, also with a resolution of 10 
                ms. Since the underlying Swing Timer processes the timing events one by one, 
                and since the gating resolution of the timer is what it is, you'll actually 
                end up with an effective resolution of 32 ms for each of these Animators.<br/>
                Now consider the model of the new animation engine, where there is just one single
                underlying
                timer running, sending out timing pulses to all animations in the system.
                This is more like 
                the multiple-TimingTargets-per-Animator model where the only gating factor in 
                resolution is that of the core timer itself, not how many Animators are
                waiting for the timing events.</li></ul>
        <p>Both of these capabilities of Timeline, grouping and the system-wide heartbeat, 
            are managed through the various <code>schedule()</code> methods of Timeline. You schedule an 
            animation to run with some offset from the beginning of a Timeline, and the 
            Timeline ensures that that animation will start when it needs to and thereafter
            receive 
            the master heartbeat events from the system. You can schedule other animations
            all on that same Timeline or on other Timelines and then schedule 
            the Timelines themselves to start when appropriate.</p>
            <pre>            Timeline t1 = new Timeline();
            // ... schedule animations on Timeline t1 ...
            
            Timeline t2 = new Timeline();
            // ... schedule animations on Timeline t2 ...
            
            // Timeline t3 = new Timeline();
            // schedule t1 to start 100 ms after t3 starts
            t3.schedule(t1, 100);
            // schedule t2 to start 200 ms after g3 starts
            t3.schedule(t2, 200);
            // start t3
            t3.start();            </pre>
        <p>An important point to note here is that Timelines and Clips may both be 
            scheduled on a Timeline. The <code>schedule()</code> methods actually 
            take an <code>Animation</code>
            parameter, where Animation is a superclass of both Clip and Timeline. So a 
            Timeline itself can be started relative to some point in another 
            Timeline. In this way, we can create hierarchical groups of animations 
            that are automatically triggered according to how we scheduled them together.</p>
        <h3>
            MotionPath</h3>
        <p>
            One constraint of the TimingFramework is that while time could be interpolated
            non-linearly (using a non-linear Interpolator object), space was always interpolated linearly.
            For example, if you set up an animation between points <i>(x0, y0)</i> and <i>(x1, y1)</i>, then
            the system would interpolate intermediate <em>(x, y)</em> points linearly between
            these points; all points calculated
            by the system (by the old Evaluator class) would lie along a straight line drawn between
            the two endpoints.</p>
        <p>
            The new <code>MotionPath</code> class makes it possible to create keyframes, and an Evaluator
            to interpolate between them, for curved paths.</p>
        <h2>
            What Now? Whither TimingFramework?</h2>
        <p>
            A logical question to ask now is, what about the Timing Framework? Is there a future
            in that project? Or should I start using the scene graph animation library instead?</p>
        <p>
            I think the answer to these questions is still being figured out (since the scene
            graph library itself is still very much in-development), but here are a
            couple of reasonable ways to think about it, depending on your timeframe:</p>
        <h3>
            Short-term</h3>
        <p>
            The TimingFramework is in good shape in general. There was a reason that I declared
            it 1.0 (I didn't just randomly decide to add .44 to the previous release numbered
            0.56). So please continue to use it as you see fit in your work for now. There are
            some minor issues that crop up occasionally that should probably be addressed in
            that library (although I admit I have been a bit preoccupied on Scene Graph and
            other things for a while and haven't been as responsive to issues as I'd like).</p>
        <p>
            Scene Graph animation, on the other hand, is very much in flux right now. We're
            reasonably happy with the functionality of the library, but I wouldn't be shocked
            to see some more refactoring take place as we continue working on the Scene Graph
            project in general. So while I encourage you to take a look at it and play around
            with it, I wouldn't bet on the current implementation of it quite yet.</p>
        <h3>
            Long-term</h3>
        <p>
            I think (and this is where it gets fuzzy, because we're a bit busy focusing on the
            short-term right now and just trying to finish up the Scene Graph library in general)
            that the scene graph animation engine, or something very like it, will probably
            be the single library for animation eventually. It just doesn't make sense to have
            two such libraries, at least not
            coming out of the same group at Sun and not when
            one is essentially a subset of the other. When we get there and what the eventual,
            single library looks like when we're there is still a mystery. But long term, I
            see these libraries converging, and probably looking more like the Scene Graph version
            than Timing Framework.</p>
        <p>
            But in the meantime, please use the Timing Framework while you investigate and starting
            playing with the Scene Graph animation engine. <a href="https://scenegraph.dev.java.net/#getinvolved">
                Send us feedback</a> on what we could improve to make sure that the
            library we eventually end up with supports what you need from it.</p>
        <h2>
            By the Way</h2>
        <p>With all of this power to do cool, whizzy animations in Desktop Java 
            applications, I'm thinking that "Scene Graph" isn't really a good enough name. Here's a possible
            alternative that I'm proposing, as of now:</p>
        <h2 style="text-align: center">
            <em>Obscene</em></h2>
        <p>But it still feels like something's missing. Maybe it's just not graphic enough.</p>
]]>

</content>
</entry>
<entry>
<title>Been There, Scene That</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/chet/archive/2008/01/been_there_scen.html" />
<modified>2008-01-04T22:27:16Z</modified>
<issued>2008-01-04T22:27:04Z</issued>
<id>tag:weblogs.java.net,2008:/blog/chet/81.8927</id>
<created>2008-01-04T22:27:04Z</created>
<summary type="text/plain">Part 1 of a two-part article on the animation engine in the Scene Graph project.  A moving tale.</summary>
<author>
<name>chet</name>


</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/chet/">
<![CDATA[	<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
	</script>
	<script type="text/javascript">
  var urchinCalled;
  if (!urchinCalled) {
	_uacct = "UA-1223303-2";
        urchinCalled = true;
        urchinTracker();
  }
	</script>
	<script src="http://weblogs.java.net/blog/chet/archive/javanetblogbar.js" type="text/javascript"></script>
<p>
<em>
(This is Part 1 of a two-part blog. It's been broken in two for no particularly good reason other 
than it was getting a bit long for a single entry and I always like a bit of suspense and
tension in my technical articles - don't you?
. Look for Part 2 in the next few days)
</em>
</p>
        <p>You may have already heard about the <a href="http://scenegraph.dev.java.net">Scene
                Graph project</a> that we released last 
            month on java.net.
        </p>
        <p>In case you haven't heard about it yet, here's some information about it: </p>
        <p style="text-align: center">
            We released the project last month on java.net.</p>
        <p>Since the team was pretty busy at the time (I was at <a href="http://javapolis.com">
                JavaPolis</a> talking about the 
            project, among other things, and the team was cranking away on the actual 
            code), we haven't really gotten around to blogging about it yet to tell people 
            more about the project (hey, the code's out there - does anyone need anything 
            more?). Fortunately for us, <a href="http://weblogs.java.net/blog/joshy/">
                Josh</a> seems to blog in his sleep, so there's at least been some information
            floating
            out there in the blogosphere. But maybe now that the library is available, we should actually 
            talk about it to help everyone understand what it is, how it works, and what 
            you can do with it.</p>
        <p>
            <a href="http://weblogs.java.net/blog/hansmuller/">Hans Muller</a> is working an
            intro/overview on the subject. <a href="http://weblogs.java.net/blog/campbell/">Chris Campbell</a> has a blog in the works on scene graph image effects. And I was tasked with (surprise, surprise) a 
            discussion of animation.</p>
        <h2>TimingFramework++</h2>
        <p>I think that the best way to describe the animation engine in the scene graph 
            project is that it is like the next major version of the <a href="http://timingframework.dev.java.net">
                Timing Framework</a>. Maybe it's because I'm a graphics geek, but I always find
            it easier to understand concepts through pictures. So here's a technical diagram
            illustrating how the scene graph animation engine relates to the Timing Framework.
            It's a bit technical, but hopefully you'll get the point.</p>
        <p style="text-align: center">
            <img alt="SceneGraphAnimationPicSm.gif" src="http://weblogs.java.net/blog/chet/images/SceneGraphAnimationPicSm.gif" width="595" height="408" />

</p>
        <p>
            The similarlity between the two libraries is not, obviously, a coincidence. We started with the 1.0 version 
            of the Timing Framework and changed it to suit our needs for the scene graph, where "suit our needs" means that we refactored the API to improve upon various things and added functionality that has so far 
            been lacking in the Timing Framework.</p>
        <p>Rather than explain how the Timing Framework works, I'd encourage you to check 
            out the <a href="http://timingframework.dev.java.net">project</a>, the docs linked on the <a href="http://timingframework.dev.java.net">project site</a>, the demos for that project, and 
            the copious other amounts of information on the library (including demos, 
            chapters in the <a href="http://filthyrichclients.org">Filthy Rich Clients</a>
            book, and so on). I'll assume that 
            anyone reading past here has some passing familiarity with the Timing 
            Framework.</p>
        <p>I'll step through the major categories of differences between the 
            TimingFramework and this new animation library, to give a sense of what's new 
            in the scene graph. I'll show some sample code along the way, although I'd encourage you to check out
            the <a href="https://scenegraph.dev.java.net/#downloads">Nodes example</a> on the
            <a href="http://scenegraph.dev.java.net">scene graph site</a> to see animation usage in action.</p>
        <h2>Refactoring: What's Changed?</h2>
        <h3>Clip is the new Animator</h3>
        <p>After living for way too long with the bureaucratically dull name 
        <code>TimingController</code>
            that came from the original version of the Timing Framework, we finally 
            renamed that class to the friendlier <code>Animator</code> name that the library enjoys 
            today in version 1.0. But now it's changed again. That 
            class, the most fundamental in the whole library, is now called <code>Clip</code>. This 
            was done to help people that might be familiar with the concepts covered by 
            that class in other toolkits and environments where the name Clip is common. It's also 
            closer to what the object is; yes, it animates things, but it's really just a 
            short, atomic animation which is meant to be strung together with other 
            animations in an application, much like short clips are edited together to make 
            an entire movie (or, in the case of the
            Fantastic Four sequel, to make a travesty).</p>
        <p>Besides, <code>Clip</code> saves 4 characters every time you type it. Pretty cool, huh? 
            That's like several milliseconds of coding time per day that we've saved you, our 
            user. All part of the 
            job, providing service and performance with a smiley.</p>
        <p> Clip has a handful of factory methods for the common cases:</p>
        <pre>
            create(int duration, double repeatCount, Object target, 
                   String property, T... keyValues)

            create(int duration, double repeatCount, Property property, T... keyValues)

            create(int duration, double repeatCount, TimingTarget target)

            create(int duration, Object target, String property, 
                   T... keyValues)

            create(int duration, Property property, T... keyValues)

            create(int duration, TimingTarget target)
        </pre>
        <p>
            (The Property object will be explained later, but think of it as a replacement for
            the previous PropertySetter object in the Timing Framework).</p>
        <p>
            Like Animator, Clips begin running when the start() method is called (although
            Clip also has more involved and powerful scheduling capabilities, discussed later):</p>
        <pre>            // Fade in myObject over a half second
            Clip clip = Clip.create(500, myObject, "opacity", 0f, 1f);
            clip.start();
        </pre>
        <h3>PropertySetter is now BeanProperty</h3>
        <p>The old way of having the animation engine automatically set object/property 
            values was through the PropertySetter class, which was constructed with a given 
            object and property-name pair. We felt that this was a bit too constrictive in 
            a world where there might be other ways that one might want to set values on 
            objects; what if someone has an object without JavaBean-like getter/setters on 
            it?</p>
        <p>So we defined a new interface, <code>Property</code>, that abstracts out the concepts and methods for getting and setting the value of some property.
        </p>
        <pre>            public interface Property&lt;T&gt; {
                
                public &lt;T&gt; getValue();
                
                public void setValue(T value);
            }</pre>
        <p>Then we refactored the old <code>PropertySetter</code> class as the new class 
        <code>BeanProperty</code>, 
            which is an implementation of that interface that specifically defines 
            properties in terms of JavaBean objects/name pairs.</p>
        <pre>            public class BeanProperty&lt;T&gt; implements Property&lt;T&gt; {
                
		public BeanProperty(Object object, String propertyName);

                public &lt;T&gt; getValue();
                
                public void setValue(T value);
            }</pre>
        <p>Also, note that we separated the functionality of setting values on a Property object
            from animating those values. These concepts overlapped in the previous 
            PropertySetter object, which was an implementation of TimingTarget and handled 
            both animating the value in question as well as setting it on the specified 
            object. Now, the new KeyFrames object handles animating a property, and the 
            resulting value is then sent into the appropriate Property object.</p>
        <h3>Interpolators</h3>
        <p>One of my favorite refactorings from the TimingFramework was the change that Chris
            Campbell made to interpolators. The base interface, <code>Interpolator</code>, is the same:</p>
            <pre>            public interface Interpolator {
            
                public float interpolate(float fraction);
                
            }</pre>
        <p>
            The change is that there used to be several implementation classes of 
            Interpolator (<code>LinearInterpolator</code>, <code>DiscreteInterpolator</code>, and 
            <code>SplineInterpolator</code>), and now there is just one class, Interpolators, 
            that provides five factory 
            methods for different types of interpolators:</p>
            <pre>            public class Interpolators {
            
                static Interpolator getLinearInstance();
                
                static Interpolator getDiscreteInstance();
                
                static Interpolator getSplineInstance(float x1, float y1, float x2, float y2);

                static Interpolator getEasingInstance();
                
                static Interpolator getEasingInstance(float acceleration, float deceleration);
                
            }</pre>
        <p>The linear, discrete, and spline interpolators are virtually the same as 
        before, in both construction and 
            operation. But there is now an additional "easing" variety that takes the place 
            of the <code>setAcceleration()</code>/<code>setDeceleration()</code> behavior in the old Animator class. 
            This simplifies the use of acceleration/deceleration, and makes it more 
            consistent with the use of other interpolator functionality.</p>
        <p>Also, note that Clip uses an easing interpolator by default (with the default factors
            of .2f/.2f), as opposed 
            to the old linearly-interpolated Animator object. Linear interpolation makes 
            more sense as a default from an analytical standpoint (it seems less arbitrary 
            than some particular choice of easing factors), but frankly most of the animations that 
            you'll create should be non-linearly interpolated, which means that you would either not get the behavior you should if you used the linear
            default or (as in all of my animation demos) you'd have to keep writing the same 
            boilerplate code to set the easing factors to get the behavior right.</p>
        <h3>KeyFrames</h3>
        <p>The previous structure of <code>KeyFrames</code> was closely modeled on the <a href="http://www.w3.org/AudioVideo/">
                SMIL</a> approach, 
            where there was a list of <i>n</i> <code>KeyTimes</code>, a list of <em>n</em>
            <code>KeyValues</code> which corresponded 
            to the times in KeyTimes, and an optional list of <i>(n-1)</i> <code>Interpolators</code> for the 
            intervals between the times in KeyTimes. The basic functionality of that system 
            is unchanged, but it has been reorganized in a way that we think makes more 
            sense for the API.</p>
        <p>
            Now there is a <code>KeyFrame</code> object which holds a time/value pair as well as an optional <code>Interpolator</code>. The Interpolator is used for the interval between the previous 
            KeyFrame and this one (which is ignored if this is the first
            KeyFrame, since there is no preceding interval). A <code>KeyFrames</code> object in the new system is just a 
            collection of these individual KeyFrame objects. There is also more latitude now for 
            creating animations without start/end values. For example, if a KeyFrames 
            object is defined without a KeyFrame object at time <em>t=0</em>,
            then the animation 
            derives the value at <em>t=0</em> when the animation is started. Additionally, if there is no KeyFrame at time <em>t=1</em>, then the animation simply holds the value set by the 
            preceding KeyFrame.</p>
        <p>KeyFrames implement the TimingTarget interface, and are used as targets of an 
            animation to animate a value and then set it on the Property object with 
            which they were constructed.
            Note that KeyFrames objects are created either with an explicit Property object
            or with the object/property
            pair that is used to construct a BeanProperty object internally:</p>
            <pre>            static KeyFrames&lt;T&gt; create(Object target, String propertyName, KeyFrame&lt;T&gt;... keyFrames);
            
            static KeyFrames&lt;T&gt; create(Object target, String propertyName, T... keyValues);
            
            static KeyFrames&lt;T&gt; create(Property&lt;T&gt; property, KeyFrame&lt;T&gt;... keyFrames);
            
            static KeyFrames&lt;T&gt; create(Property&lt;T&gt; property, T... keyValues);
            </pre>
        <h3>
            Evaluator is now Composer</h3>
        <p>The system in TimingFramework to handle interpolation between values of various 
            types uses the <code>Evaluator</code> class (or, rather, subclasses of Evaluator). Each Evaluator subclass is defined to take values of a certain type, a fraction
            to interpolate between then, and would linearly interpolate between those values.
            Chris 
            abstracted this functionality another level and created the <code>Composer</code> class. It 
            performs similar functionality, but only requires from its subclasses the 
            work of breaking down a type into component pieces that are stored in 
            double values. That is, the Evaluator class internally handles the simple 
            parameteric calculation that interpolates between two double values. All that 
            Composer and its subclasses need to do is to marshall values between their 
            native representation and a representation in a series of doubles.</p>
        <p>
            As in the TimingFramework, most types that you would care about animating are 
            already handled by the system. But if you do need to animate a variable of a type 
            that is unknown to the system, then you need to create your own Composer subclass and register it 
            with the system. It will then be used whenever the system encounters that type 
            and looks for an appropriate Composer. Instead of putting sample code for a here, I'll just defer to the JavaDocs
            and the source code, which do a good job of showing what any new subclass would
            need to do in order to work within this system. But assuming you've defined some
            custom Composer, MytypeComposer, registration is easy:</p>
            <pre>            Composer.register(new MytypeComposer());
            </pre>
        <h3>TimingTrigger is replaced by Clip dependency scheduling</h3>
        <p>One piece of functionality that is completely gone is the old 
        <code>TimingTrigger</code>. 
            This class is the mechanism for sequencing animations in the Timing Framework; 
            you daisy-chain animations by triggering one animation to start when 
            another ended. But now, the Clip class has this capability built-in, with more 
            bells and whistles. Instead of going through a Trigger to sequence animations, 
            you can tell the animations directly that you want to sequence them on each 
            other. Also, there is more flexibility in how the animations are sequenced; you 
            can schedule an animation to start on another animation's start or end, and can 
            do either one with a specified offset value. </p>
            <pre>            addBeginAnimation(Animation anim);
            
            addBeginAnimation(Animation anim, long offset);

            addEndAnimation(Animation anim);
            
            addEndAnimation(Animation anim, long offset);          </pre>
        <p>
            (where Animation is the superclass
                of both Clip and the as-yet-undiscussed Timeline class).</p>
        <p>
            So, for example, you can have 
            clipB start 100 ms after clipA ends with the following call:</p>
        <pre>	clipA.addEndAnimation(clipB, 100);</pre>
        <h3>Minor Changes</h3>
        <p>There are various minor changes to the system that you will notice as you try it 
            out. It's not worth going through all of these (because it'd take me a long 
            time to go over the API to catch all of these changes, for one thing), but they
            should be fairly self-explanatory when you encounter them. For example, the old 
            <code>Animator.INFINITE</code> constant, which was used, for example, to define unending 
            animations has become <code>Clip.INDEFINITE</code>. Not a big change, but it seemed more 
            semantically correct.</p>
        <p>
            <em>
        (That's it for this entry - check back next week for the gripping conclusion to this discussion, as we go over some of the new bits in the scene graph animation library that are not now part of the Timing Framework) </em>
        </p>
]]>

</content>
</entry>
<entry>
<title>My JavaPolis07 Slides</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/chet/archive/2007/12/my_javapolis07.html" />
<modified>2007-12-20T19:46:01Z</modified>
<issued>2007-12-20T19:11:00Z</issued>
<id>tag:weblogs.java.net,2007:/blog/chet/81.8872</id>
<created>2007-12-20T19:11:00Z</created>
<summary type="text/plain">Here are the slides from my 3 JavaPolis presentations: Scene Graph, Filthy Makeover, and Future Java Consumer Releases.</summary>
<author>
<name>chet</name>


</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/chet/">
<![CDATA[	<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
	</script>
	<script type="text/javascript">
  var urchinCalled;
  if (!urchinCalled) {
	_uacct = "UA-1223303-2";
        urchinCalled = true;
        urchinTracker();
  }
	</script>
	<script src="http://weblogs.java.net/blog/chet/archive/javanetblogbar.js" type="text/javascript"></script>
        <P>I just returned (after a couple of long and fun flights,&nbsp;described on&nbsp;<A href="http://chetchat.blogspot.com/2007/12/plain-fright.html">my 
                other blog posting</A>)&nbsp;from <A href="http://javapolis.com">JavaPolis</A>, 
            a fantastic conference on all things Java (and some not) in Antwerp, Belgium.
        </P>
        <P>I know what you're thinking: "I wish I could visit northern Europe in December. 
            It's such a gray, wet, cold time of year." And you're right. I found Antwerp particularly inviting to visit with all of the warmest clothes I own; light, cotton articles that are able to sustain freezing California temperatures down to nearly 65 degrees Fahrenheit. 
</p>
<p>
It's true that 
            JavaPolis does not suffer the weather distractions of events in other cities 
            such as San Francisco, Orlando, or Duluth. It's like what a friend of mine said 
            who worked for&nbsp;a large software company&nbsp;in Redmond, Washington. 
            Everyone there works&nbsp;long hours&nbsp;because, well, there's not much 
            reason to go outside between, like, September and June. So you might as well 
            stay in the office and keep hacking. At JavaPolis, you might as well attend 
            another session. Or have another Belgian beer.&nbsp; Try the Lambic. Or the 
            Geuze. Or the Kriek (cherry-flavored Geuze), if you can find one that's not too 
            sweet.</P>
        <P>You should try&nbsp;to attend&nbsp;next year, but register early - it sold out 
            this year. It definitely has the highest chair-comfort-per-Euro of any 
            conference I've been to .&nbsp;Swank movie theaters are awesome for this kind 
            of event. Unless you're the presenter, in which case you have the distinct 
            impression that the entire audience is sleeping through your talk because 
            everyone's settled so comfortably and quietly into their seats.</P>
        <P>I'll let other <A href="http://javapolis.com/confluence/display/JP07/External+Blogs">
                bloggers</A> cover the spectrum of what they saw at the conference. I 
            will&nbsp;just stick to posting my presentations here in case anyone's 
            interested. Note that the Scene Graph and Filthy Makeover sessions will 
            eventually be online in video form at <A href="http://parleys.com">parleys.com</A>; 
            think of these presentations as placeholders until the real deal is posted.</P>
        <P><A href="http://weblogs.java.net/blog/chet/archive/SceneGraph.pdf">Scene Graph</A>: 
            This presentation was at the end of Richard Bair's university day session, 
            entitled "Swinging RIAs." It's an introduction to the new <A href="http://scenegraph.dev.java.net">
                Scene Graph project</A> posted on java.net, which is a module of the Java 
            FX platform and is now available in early early [early] access form for Java 
            developers.</P>
        <P><A href="http://weblogs.java.net/blog/chet/archive/FilthyMakeover.pdf">Filthy 
                Makeover</A>: This presentation was a combination of&nbsp;prior <A href="http://filthyrichclients.org">
                Filthy Rich Clients</A>&nbsp;and as Extreme GUI Makeover talks (from the 
            past couple of JavaOne conferences). The talk covered a sampling of filthy rich 
            techniques and then showed them in action in the context of larger applications 
            from the GUI Makeover talks. Then I walked through some code in the editor to 
            show how, when you get right down to it, the code to enable the effects in real 
            applications is pretty darn close to the code as described for filthy rich 
            clients. The video for this presentation&nbsp;should be&nbsp;particularly 
            interesting, or at least more involved than the slides here, since much of the 
            new content for the talk was in the interactive demos and code walkthroughs, 
            which are represented in this slide deck by&nbsp;less informative&nbsp;"Demo" 
            slides.</P>
        <P><A href="http://weblogs.java.net/blog/chet/archive/JavaConsumerReleases.pdf">Future 
                Java Consumer Releases</A>: This&nbsp;BOF was about the upcoming Update N 
            and Java FX releases, and discussed the various features going into these 
            releases. There won't be a video of this talk (BOF's don't get that special 
            treatment), but the slides are hopefully self-explanatory.</P>
]]>

</content>
</entry>
<entry>
<title>Review Review</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/chet/archive/2007/11/review_review.html" />
<modified>2007-11-15T14:56:26Z</modified>
<issued>2007-11-15T14:56:19Z</issued>
<id>tag:weblogs.java.net,2007:/blog/chet/81.8660</id>
<created>2007-11-15T14:56:19Z</created>
<summary type="text/plain">Still wondering whether Filthy Rich Clients is something you should read?  Check out Geertjan&apos;s review of it.</summary>
<author>
<name>chet</name>


</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/chet/">
<![CDATA[	<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
	</script>
	<script type="text/javascript">
  var urchinCalled;
  if (!urchinCalled) {
	_uacct = "UA-1223303-2";
        urchinCalled = true;
        urchinTracker();
  }
	</script>
	<script src="http://weblogs.java.net/blog/chet/archive/javanetblogbar.js" type="text/javascript"></script>
<p>
I don't like to toot my own horn, but I'm happy if others happen to toot it for me.
</p>
<p>
Geertjan Wielenga has <a href="http://blogs.sun.com/geertjan/entry/filthy_rich_clients_the_book">posted a review</a> of <a href="http://filthyrichclients.org">Filthy Rich Clients</a> on <a href="http://blogs.sun.com/geertjan">his blog</a>.
</p>
<p>
If you're still wondering whether this book is for you, check out <a href="http://blogs.sun.com/geertjan/entry/filthy_rich_clients_the_book">the review</a>. Geertjan does the best job I've seen yet of describing the content and the reasons why any Swing developer should read it.
</p>
<p>
Or if you're still wondering what Swing is and what book I'm talking about, then I have no idea what you're doing here to begin with.  But I'd encourage you to get the book anyway.
</p>
]]>

</content>
</entry>
<entry>
<title>Of Pros and QCons</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/chet/archive/2007/11/of_pros_and_qco.html" />
<modified>2007-11-09T18:56:03Z</modified>
<issued>2007-11-09T18:55:53Z</issued>
<id>tag:weblogs.java.net,2007:/blog/chet/81.8617</id>
<created>2007-11-09T18:55:53Z</created>
<summary type="text/plain">In case you missed QCon on Wednesday, here&apos;s my favorite question that came out of the panel I was on.</summary>
<author>
<name>chet</name>


</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/chet/">
<![CDATA[	<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
	</script>
	<script type="text/javascript">
  var urchinCalled;
  if (!urchinCalled) {
	_uacct = "UA-1223303-2";
        urchinCalled = true;
        urchinTracker();
  }
	</script>
	<script src="http://weblogs.java.net/blog/chet/archive/javanetblogbar.js" type="text/javascript"></script>
<p>
I spent Wednesday at QCon, in San Francisco, giving a presentation on <a href="http://qcon.infoq.com/sanfrancisco/presentation/Java+Comes+Home+to+the+Consumer">Java's new consumer focus</a> and participating on a panel with the auspicious title, <a href="http://qcon.infoq.com/sanfrancisco/presentation/Panel%3A+What+will+the+future+of+Java+development+be%3F">What Will the Future of Java Development Be?</a>.
</p>
<p>
I wrote a bit about one of the panel discussions for <a href="http://www.regdeveloper.co.uk/2007/11/09/haase_opnion_java_future/">The Register</a>, so I won't repeat that stuff here. Instead, I wanted to just repeat my favorite question that came up that evening. It was in my original article for The Register, but it got edited out (maybe it was too off-topic). Lucky for me I have this other outlet specifically designed for off-topic topics.  So here it is:
</p>
<p>
<blockquote>
<i>A good language changes the way we think about programming. What language
change
would you like to see that would change the way we think?"
</i>
</blockquote>
</p>
<p>
I found the question itself confusing. I mean,
if I could imagine something that would change the way I thought,
then wouldn't I already think that way? It seemed like I
could easily fall into an infinite recursion loop, overrun
my stack, and have a brain fault. 
</p>
<p>
All of us had to answer that one, so I mumbled out something about improving the overall platform (not just the language). But mostly, I was busy trying to reboot my brain.
</p>]]>

</content>
</entry>
<entry>
<title>Old JavaOne Presentations Never Die</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/chet/archive/2007/11/old_javaone_pre.html" />
<modified>2007-11-08T16:54:54Z</modified>
<issued>2007-11-08T16:54:16Z</issued>
<id>tag:weblogs.java.net,2007:/blog/chet/81.8606</id>
<created>2007-11-08T16:54:16Z</created>
<summary type="text/plain">Old JavaOne presentations never die - they just get removed from the archival site. Here&apos;s a reprise of an &quot;Advanced 2D&quot; talk that I did with Phil Race and Doug Felt in 2005.</summary>
<author>
<name>chet</name>


</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/chet/">
<![CDATA[	<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
	</script>
	<script type="text/javascript">
  var urchinCalled;
  if (!urchinCalled) {
	_uacct = "UA-1223303-2";
        urchinCalled = true;
        urchinTracker();
  }
	</script>
	<script src="http://weblogs.java.net/blog/chet/archive/javanetblogbar.js" type="text/javascript"></script>
<p>
The presentation that Doug Felt, Phil Race, and I did in 2005 has the best description+diagrams of text measurement in Java 2D that I have seen. It's so useful, in fact, that I put a link to the talk in one of the footnotes of <a href="http://filthyrichclients.org">the book</a> (footnote 15, p. 78). (By the way, the great text descriptions were all due to Phil and Doug - I was just blathering on about graphics and animation, which should come as a shock to absolutely nobody).
</p>
<p>
Imagine my surprise when I discovered that the link was dead and that the presentation is no longer available on the JavaOne site. Apparently, there is a 2-year-archive policy, so all of the 2005 presentations are no longer stored.  Maybe they figure that content that old can't possibly be relevant anymore, but for presentations on APIs that live longer than 2 years, that's not necessarily true.
</p>
<p>
Anyway, I am posting the talk here mostly so that I can post a hopefully more permanent link in a corrected footnote (for the third printing, which is apparently going to press soon!). But I encourage you to take a look at the presentation if you're interested in text measurement (or Graphics Effects or Text Rendering or Printing, which we also cover in the slides). People that follow my blog and book will see some earlier versions of <a href="http://filthyrichclients.org">Filthy Rich</a> topics in my slides. For example, the original work in <a href="http://animatedtransitions.dev.java.net">Animated Transitions</a> came out of work related to this presentation - it just took a bit more time to settle down into the utility library that is discussed in <a href="http://filthyrichclients.org">the book</a> and published on the <a href="http://animatedtransitions.dev.java.net">project site</a>. I was already thinking about filthy rich content; I just needed a catchy name for it...
</p>
<p>
Here's the presentation: <a href="http://weblogs.java.net/blog/chet/archive/Advanced2D-J1-2005.pdf">Advanced Java 2D for Desktop Applications</a>.
</p>
<p>
Enjoy.
</p>]]>

</content>
</entry>
<entry>
<title>Submit a JavaOne Proposal NOW!</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/chet/archive/2007/11/submit_a_javaon.html" />
<modified>2007-11-07T15:34:50Z</modified>
<issued>2007-11-07T15:34:44Z</issued>
<id>tag:weblogs.java.net,2007:/blog/chet/81.8583</id>
<created>2007-11-07T15:34:44Z</created>
<summary type="text/plain">Tick, tick, tick.... The JavaOne Call for Papers closes on November 16th. It&apos;s only an abstract. Just one little abstract. And it&apos;s free! Come on - you can do it...</summary>
<author>
<name>chet</name>


</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/chet/">
<![CDATA[	<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
	</script>
	<script type="text/javascript">
  var urchinCalled;
  if (!urchinCalled) {
	_uacct = "UA-1223303-2";
        urchinCalled = true;
        urchinTracker();
  }
	</script>
	<script src="http://weblogs.java.net/blog/chet/archive/javanetblogbar.js" type="text/javascript"></script>

<p>
    The <a href="https://www28.cplan.com/cfp_prod/CFPLogin.jsp?wId=72T235">JavaOne Call for Papers</a> deadline always sneaks up on me. It's like jet
    lag; one minute
    you're productively cranking out code, then suddenly you're asleep
    on the keyboard, drooling on the spacebar.</p>
    <p>
Like previous years, we want to encourage as much external participation in the
        conference as possible. We know there are great Desktop Java applications being
        written and deployed out in the real world; we'd like you to come talk about them
        at the conference. Case studies, techniques, tricks, in-depth discussions of technologies,
        frameworks and architectures for productive development,
        whizzy cool effects - anything that others want to learn about is fair game.</p>
    <p>
        You only have until November 16th (that's next Friday for anyone currently time-confused
        by the Daylight Savings Time switch last weekend), so <a href="https://www28.cplan.com/cfp_prod/CFPLogin.jsp?wId=72T235">
            get your abstracts in</a> now. <a href="https://www28.cplan.com/cfp_prod/CFPLogin.jsp?wId=72T235">
        Submitting a proposal</a> isn't that much work - you just need to put enough
        information in the abstract and the outline in order for the track team to be able
        to understand what you're covering, how your going to do it, and why people would
        want to attend the talk.</p>
    <p>
        So wake up, wipe the drool off the keyboard, and <a href="https://www28.cplan.com/cfp_prod/CFPLogin.jsp?wId=72T235">
            submit that proposal</a>. Help us create and present a great Desktop track this
        year!</p>
]]>

</content>
</entry>
<entry>
<title>Male Pattern Boldness</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/chet/archive/2007/10/male_pattern_bo.html" />
<modified>2007-10-30T22:51:39Z</modified>
<issued>2007-10-25T16:03:56Z</issued>
<id>tag:weblogs.java.net,2007:/blog/chet/81.8493</id>
<created>2007-10-25T16:03:56Z</created>
<summary type="text/plain">Isn&apos;t it time that we had more software design patterns to help us in our difficult and treacherous jobs?</summary>
<author>
<name>chet</name>


</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/chet/">
<![CDATA[	<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
	</script>
	<script type="text/javascript">
  var urchinCalled;
  if (!urchinCalled) {
	_uacct = "UA-1223303-2";
        urchinCalled = true;
        urchinTracker();
  }
	</script>
	<script src="http://weblogs.java.net/blog/chet/archive/javanetblogbar.js" type="text/javascript"></script>
    <p>
        Longtime readers of my blog will know that 
        <a href="http://weblogs.java.net/blog/chet/archive/2003/08/patterns_shmatt.html">I'm a huge fan of Design Patterns</a>. Patterns wrap complex architectures with simplistic
        descriptions. They create wonderful
        buzzwords that we can use instead of resorting to actual 
        human language descriptions. And they help enforce that feeling that we're all
        a part of an elite clique shunned by society not by
        their choice, but by ours.
        </p>
    <p>
        So it is with much happiness and joy (refer to the <i>Joyous Configuration</i>
        pattern for more background on this emotion) that I hereby announce more
        patterns to help the software community in the tedious and underappreciated lives
        that we lead.
        </p>

        
    <h3>Refactory</h3> 
    <blockquote>
    <p>
    The <i>Refactory</i> pattern, a spin-off of the earlier
    <a href="http://en.wikipedia.org/wiki/Factory_method_pattern" title="Factory method pattern">Factory</a>
    pattern, is useful for engineering teams that 
    enjoy the infinite redesign
    cycle of software. While the code may work perfectly well in some configuration,
    chances are great that the entire code base can be completely refactored to 
    have the same functionality, but with different class hierarchies, 
    indenting styles, and naming
    conventions. This pattern provides for such standard refactoring methods as 
    <code>arbitraryRename()</code>,
    <code>codeRestyler()</code>, <code>classHierarchyFlattener()</code>, and 
    <code>classHierarchyExpander()</code>. This
            single pattern is often credited with being the cornerstone of 
            our entire industry.
        </p>
    </blockquote>
    <h3>Delicate</h3>
    <blockquote>
        <p>
    The <i>Delicate</i> pattern, like the traditional <a href="http://en.wikipedia.org/wiki/Delegation_pattern" title="Delegation pattern">
    Delegate</a> pattern, 
    is signified by its extreme use of indirection and object layering, 
    where a successful
    implementation will be comprised of so many layers of API and object
    wrappers that the final result is apt to break easily and
    nondeterministically.
    As <a href="http://weblogs.java.net/blog/campbell">Chris Campbell</a>
    pointed out to me, the Delicate pattern is a critical part of the trendy 
    <a href="http://en.wikipedia.org/wiki/Agile_software_development">Fragile Programming</a>
            methodology.
    </p>
        </blockquote>
    <h3>Obliterator</h3> 
    <blockquote>
    <p>
    The <i>Obliterator</i> pattern is a combination of the 
    <a href="http://en.wikipedia.org/wiki/Iterator_pattern" title="Iterator pattern">Iterator</a> pattern, 
    which is useful for walking
    through a list of objects, and deletion functionality. When applied to any list
    of objects,
    it automatically walks the list and deletes all members, then removes the list,
    the calling function, and the application itself. Variations of the pattern
    have been known to also destroy the operating system, the computers
    running the system, the networks on which the pattern is deployed,
    and the universe in which the pattern exists. Use with care, or at
    least ask your users to test it for you before declaring the product final.</p>
    </blockquote>
    <h3>Veneer</h3>
    <blockquote>
    <p>
    The <i>Veneer</i> pattern is a thin, attractive wrapper on top of a 
    rat's nest of spaghetti code. The pattern is similar to its forerunner,
    the <a href="http://en.wikipedia.org/wiki/Facade_pattern" title="Facade pattern">Façade</a> pattern, 
    except that it avoids the use of special internationalized
    letters that make correct spelling difficult for English programmers.</p>
    </blockquote>
    <h3>Disfunctional</h3>
    <blockquote>
    <p>
    Contrary to the related 
    <a href="http://en.wikipedia.org/wiki/Functional_design" title="Functional design">Functional Design</a> 
    pattern, the <i>Disfunctional</i> 
    pattern requires every component of a system
    to know about and perform every possible operation. Variants of the
    pattern exist, such as the <i>Gossip</i> and <i>Nosey Parker</i> patterns.
    </p>
    </blockquote>
    <h3>Lethargic Initialization</h3>
    <blockquote>
    <p>
    Like the <a href="http://en.wikipedia.org/wiki/Lazy_initialization_pattern" title="Lazy initialization pattern">
    Lazy Initialization</a> pattern, the <i>Lethargic Initialization</i> 
    pattern delays creation and calculation
    until such time as it is needed. However, the Lethargic pattern 
    adds the additional requirement
    that operations be carried out slowly, if at all, and may not 
    actually complete when the
    information is needed by the system. This approach has 
    distinct advantages over the Lazy
    pattern. Systems using the Lethargic approach can never suffer the 
    performance hit that is possible with
    the Lazy pattern, because at no time is the system actually doing much,
    if any, work.
    </p>
    </blockquote>
    <h3>Single</h3>
    <blockquote>
    <p>
    Like the <a href="http://en.wikipedia.org/wiki/Singleton_pattern" title="Singleton pattern">Singleton</a> 
    pattern, the <i>Single</i> represents objects of 
    which there is only
    one instance in the system. However, the Single pattern has the important
    distinction that its objects are constantly on the search for 
    other objects to combine with, in a desperate attempt to avoid
    being stuck on their own. A Single object will
    print any line, tell any recursion tail, or go into any foo bar as it
    tries to pair off with other Singles.
    </p>
    </blockquote>
    <h3>Cunning Plan</h3>
    <blockquote>
    <p>
    Like the earlier <a href="http://en.wikipedia.org/wiki/Strategy_pattern" title="Strategy pattern">Strategy</a> 
    pattern, the <i>Cunning Plan</i> pattern cleverly 
    selects the implementation of
    an algorithm on the fly. However, this more radical approach automatically 
    selects the most devious and subversive methodology, designed to 
    undermine the entire system from within.
</p>
    </blockquote>
    <p>
        It's clear that there are many more patterns that we can invent if
        we just set our minds to the task and find appropriately obscure
        words with which to name them. But hopefully the selection above will invigorate
        the community to begin implementing brave new architectures based
        on proven, robust buzzwords.
        </p>
]]>

</content>
</entry>
<entry>
<title>Move It!</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/chet/archive/2007/10/move_it.html" />
<modified>2007-10-26T23:53:09Z</modified>
<issued>2007-10-23T15:41:23Z</issued>
<id>tag:weblogs.java.net,2007:/blog/chet/81.8477</id>
<created>2007-10-23T15:41:23Z</created>
<summary type="text/plain">Introducing Animated Transitions, a new library for the easy creation of animated segues between application states. Begin here, but then check out the java.net article and project sites, and then go use the darn thing.
</summary>
<author>
<name>chet</name>


</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/chet/">
<![CDATA[	<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
	</script>
	<script type="text/javascript">
  var urchinCalled;
  if (!urchinCalled) {
	_uacct = "UA-1223303-2";
        urchinCalled = true;
        urchinTracker();
  }
	</script>
	<script src="http://weblogs.java.net/blog/chet/archive/javanetblogbar.js" type="text/javascript"></script>
<p>
    Introducing <a href="http://animatedtransitions.dev.java.net">Animated Transitions</a>, 
    a new library for the easy creation of animated segues between application states.
    </p>
    <p>
It's been a long slog, from initial demos of the technology in a session
on "Advanced 2D" at JavaOne 2005, to use of an early version of the library
in the <a href="http://aerith.dev.java.net">Aerith</a> application, to finishing
off the library and creating more demos exercising it for the book 
<a href="http://filthyrichclients.org">
Filthy Rich Clients</a>, to getting legal approval for pushing the actual
source code (an exercise over the last several months that was
not unlike slamming the refrigerator door on my head, over and over. Every day.).
</p>
<p>
But it's finally done, and the long-awaited day is finally here:
<center>
    <h2>
    <i>
The Animated Transitions library is hereby released
</i>
        </h2>
    </center>
</p>
<p>
The project is available on java.net at <a href="http://animatedtransitions.dev.java.net">
http://animatedtransitions.dev.java.net</a> with a BSD license.
</p>
<p>
The library is fully described in Chapter 18 of <a href="http://filthyrichclients.org">
Filthy Rich Clients</a>. That chapter includes a complete description of the
library's API, detailed explanations of two sample applications that use
the library, and some nitty-gritty details on how the library internals work.
</p>
<p>
But because there are probably a couple of people left on the planet that
do not yet have a copy of the book (no idea how this happened. Maybe it's
because we have been so 
quiet about it. We should really talk more about it), and because I'm
such a nice guy and all, I wrote up a short tutorial on the basics
of using the library, along with a new demo that shows the basics in
action. You can find that tutorial in the java.net article,
<a href="http://today.java.net/pub/a//today/2007/10/23/create-moving-experiences-with-animated-transitions.html">
    "Create Moving Experiences with Animated Transitions"</a>.
</p>
<p>
In fact, here's a web-started version of the demo so that you can see it 
in action. Click on the handy image below and run 
it. Click on the More/Less buttons to see what it's all about.
Note: There are some artifacts reported on the Mac, perhaps related
to the way they treat layout and the panels that contain the buttons.
</p>
<p>
    <center>
    <a href="http://download.java.net/javadesktop/filthyrichclients/AnimatedTransitions/demos/FieldsOfText.jnlp">
<img alt="Transition1-2.png" src="http://weblogs.java.net/blog/chet/images/Transition1-2.png" width="208" height="234" />
</a>
    </center>
</p>
<p>
Play around with it. Check out the 
<a href="http://today.java.net/pub/a/today/2007/10/23/create-moving-experiences-with-animated-transitions.html">
article and the accompanying demo</a>. Check out the 
demos on the <a href="http://filthyrichclients.org">book's website</a>. 
Write your own demos. Or, even better, use the
library in your actual applications. Make those applications more dynamic
and help your users actually understand the interfaces they're beset with.
</p>
<p>
Go on: Move it!
</p>
]]>

</content>
</entry>
<entry>
<title>Filthy Download</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/chet/archive/2007/10/filthy_download.html" />
<modified>2007-10-16T16:35:33Z</modified>
<issued>2007-10-16T16:35:25Z</issued>
<id>tag:weblogs.java.net,2007:/blog/chet/81.8433</id>
<created>2007-10-16T16:35:25Z</created>
<summary type="text/plain">Filthy Rich Clients is now available for as a downloadable PDF document. No, not for free. But downloadable, anyway.</summary>
<author>
<name>chet</name>


</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/chet/">
<![CDATA[	<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
	</script>
	<script type="text/javascript">
  var urchinCalled;
  if (!urchinCalled) {
	_uacct = "UA-1223303-2";
        urchinCalled = true;
        urchinTracker();
  }
	</script>
	<script src="http://weblogs.java.net/blog/chet/archive/javanetblogbar.js" type="text/javascript"></script>
<p>
The publisher just informed us that they've made a downloadable DRM-encrypted PDF version of <a href="http://filthyrichclients.org">Filthy Rich Clients</a> available <a href="http://www.informit.com/store/product.aspx?isbn=0132345366&rl=1">here</a>. I know that some folks have been asking about this for a while, so it seemed worth another shamelessly self-promoting, yet thankfully brief, blog entry to call attention to it.
</p>
]]>

</content>
</entry>
<entry>
<title>Early Access Granted: Java SE 6 Update N</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/chet/archive/2007/10/early_access_gr.html" />
<modified>2007-10-01T19:42:36Z</modified>
<issued>2007-10-01T19:42:27Z</issued>
<id>tag:weblogs.java.net,2007:/blog/chet/81.8346</id>
<created>2007-10-01T19:42:27Z</created>
<summary type="text/plain">Java SE 6 Update N (formerly known as &quot;The Consumer JRE&quot;), the update released aimed at making Desktop Java more consumer-friendly, is available for early access testing.  Try it out and let us know how it works for you.</summary>
<author>
<name>chet</name>


</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/chet/">
<![CDATA[	<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
	</script>
	<script type="text/javascript">
  var urchinCalled;
  if (!urchinCalled) {
	_uacct = "UA-1223303-2";
        urchinCalled = true;
        urchinTracker();
  }
	</script>
	<script src="http://weblogs.java.net/blog/chet/archive/javanetblogbar.js" type="text/javascript"></script>
	<p align="center">
	    <img alt="JavaSE6UpdateNPicSm.png" src="http://weblogs.java.net/blog/chet/images/JavaSE6UpdateNPicSm.png"
		width="500" height="352" />
	</p>
	<P>It's <A href="https://jdk6.dev.java.net/6uNea.html">here</A> (almost), it's 
	    ready (for testing), and it's got a cooler name than ever before.... <A href="https://jdk6.dev.java.net/6uNea.html">
		Java SE 6 Update N</A> (formerly known as the Consumer JRE) is available 
	    for early access.</P>
	<P>Remember when I <A href="http://weblogs.java.net/blog/chet/archive/2007/05/consumer_jre_le.html">
		talked about</A> an upcoming Java SE 6 release that should address many of 
	    the outstanding issues for Java on the client? We used to call it "The Consumer 
	    JRE", but then we decided that "Java SE 6 Update N" was a much cooler name. 
	    Rolls right off the tongue. More SExy, like. Besides, as my buddy Willy 
	    Shakespeare was fond of saying:</P>
	<P><EM>What's in a name? that which we call</EM> <b><code>Java SE6 Update N</code></b><BR>
	    <EM>By any other name would smell as sweet<BR>
	    </EM>
	</P>
	<P>(I don't know what's up with the "smell" thing. I think it's poetic license.) 
	    Whatever the release is called, many of the features in the release are ready 
	    for testing. Head on over to the <A href="https://jdk6.dev.java.net/6uNea.html">download 
		page</A> and give it a whirl.</P>
	<P>Some of the important features in this release (which, by the way, should make 
	    for a better <A href="http://openjfx.dev.java.net">Java FX</A> experience when 
	    it's released), include:</P>
	<UL>
	    <LI>
		<STRONG>Java Quickstarter</STRONG>
	    : Faster coldstart for Java applications and applets
	    <LI>
		<STRONG>Deployment Toolkit</STRONG>: Easier detection of a user's Java version 
		from a web page. (Note that the current <A href="https://jdk6.dev.java.net/testing.html">
		    Testing</A>
	    page is light on details for this feature - we plan to update this item in the 
	    next couple of days with specific information about testing this).
	    <LI>
		<STRONG>Graphics Performance</STRONG>
	    : Acceleration through Direct3D on Windows for Java 2D, enabled by default
	    <LI>
		<STRONG>Nimbus</STRONG>: A new Swing cross-platform look &amp; feel that's much 
		more modern and cool than Metal. Scott Violet was saying that some look &amp; 
		feels were so cool you wanted to lick them. Along those lines, I'd claim that 
		Nimbus is our first Swing lick &amp; feel.</LI></UL>
	<P>Note that some items planned for the final release are not there yet (we're 
	    still working on them). In particular, <A href="http://weblogs.java.net/blog/enicholas/archive/2007/05/java_kernel_unm.html">
		Java Kernel</A> is still baking internally before we unleash it. So you'll 
	    have to check back in a few weeks if you want to hammer on that one.</P>
	<P>More information about what is and is not available for testing in this release 
	    so far is on the <A href="https://jdk6.dev.java.net/testing.html">Testing 
		Guidelines page</A>.</P>
	<P>Please try it out and send us <A href="https://jdk6.dev.java.net/6uNea.html#Feedback">
		feedback</A> on it. In particular, please send feedback through the handy <A href="https://jdk6.dev.java.net/6uNea.html#Feedback">
		Feedback</A> forum on the download page. Much as I enjoy the comments to my 
	    blog, I would rather have important release feedback go to the folks that are 
	    directly working on the issues to make sure that your input gets heard.</P>
]]>

</content>
</entry>

</feed>