Archive for March, 2009

Toggling Fullscreen with JavaFX

Tuesday, March 31st, 2009

JavaFX supports full screen mode via the Stage class, and it works well provided you don’t want to switch back and forth between full screen and windowed mode. If you want the ability to toggle, then a little more work is necessary.

I had read from this post that implementing a toggle is simply a matter of swapping between two Stages: a windowed and a full screen one. So let’s go ahead and do that.

Here we’ll set up a windowed Stage as we normally would, the only difference is that we’re naming it:

var windowedStage:Stage = Stage {
  onClose: function() {
    FX.exit()
  }
  title: "Fullscreen Toggle"
  width: 250
  height: 200
  scene: Scene {
    fill: Color.BLACK
    content: SwingButton {
      translateX: 75
      translateY: 50
      text: "Toggle Fullscreen"
      action: function() {
         if (windowedStage.visible) {
           toggleFullscreen(fullscreenStage, windowedStage)
         }
         else {
           toggleFullscreen(windowedStage, fullscreenStage)
         }
      }
    }
  }
  visible: true
}

Note that we have to declare it of type “Stage” since we refer to it in an anonymous function in the declaration.

Next we create a full screen stage which is initially empty and not visible:

var fullscreenStage = Stage {
  fullScreen: true
  visible: false
}

The button that initiates the toggle checks to see which of the stages is visible and passes them in the appropriate order to toggleFullscreen, which is here:

function toggleFullscreen(toVis:Stage, toNotVis:Stage) {
  toNotVis.visible = false;
  toVis.scene = toNotVis.scene;
  toNotVis.scene = null;
  toVis.visible = true;
}

Which just toggles the visibility of the two Stages and assigns the Scene to the visible Stage. Note a couple of things though:

  • After we set the Scene in the newly visible Stage we explicitly set it to null in the old (now non-visible) Stage. If we omit this step then we’re unable to switch back to this Stage later.
  • Note also that “onClose” is declared to close the application when the windowed Stage closes. If we don’t include this, the full screen stage will keep the application from exiting (even though it may not be visible).

As with everything I do, there may be a simpler way to do it, and your personal mileage may vary, but share the love, right? Right.

Griffon Book on the Way

Tuesday, March 31st, 2009

One of my semi-daily emails from Manning Publications just informed me that a new Griffon book, Griffon in Action, is on the way. It’s great to see that Griffon is gaining enough traction to have an “In Action” book published about it.

It looks like while the actual print version of the book is not due out until January of next year, the early access ebook version should be available soon.

Scrolling with JavaFX

Wednesday, March 18th, 2009

Since JavaFX has no scrolling support yet (not counting the Swing extensions), any desire to scroll around will fall to the developer to implement.

In general, I don’t recommend trying to “roll your own” components since I have faith that scrolling support will be added in future a release, but in the interim, here’s a little scrolling experiment:

The list items are wrapped Text components of arbitrary height. All of these text components are themselves contained in a Group component which is clipped to the inner rectangle of the container (this keeps the list from becoming visible above or below the container’s bounds).

The smooth scrolling is achieved by handing the “button group” to a TranslationTransition which moves the group by the height of the next item to be scrolled:

canScroll = false;
TranslateTransition {
  node: buttonGroup
  byY: curItem.boundsInLocal.height
  duration: 0.4s
  action: function() { checkScroll() }
}.play();

In order to keep the user from hammering on the scroll button while a scroll is in progress, which would cause unpredictable results, the scroll button is first disabled. At the end of the translation the “action” function is called, which will re-enable the scroll button (if there is another item to scroll).

Update: The source code is available here.

TDD: It’s Not Just For Zealots

Monday, March 16th, 2009

TDD (Test Driven Design/Development) is the practice of writing tests before writing the thing that will be tested. I’ve been simultaneously interested and suspicious of this way of writing software, trying to decide if the assumed rise in quality of the software could outweigh the dictatorial approach to writing tests (a testocracy)?

A convenient opportunity to try out TDD presented itself recently in the form of helping out on a Grails project. TDD’s autocratic approach to testing seemed like a good fit in this situation since, while I was no stranger to Groovy, this would be my first real foray into Grails.

In an effort to get up to speed in the application, and even Grails to some extent, I ended up writing 20 or so tests in the general area that I would need to be working in just to verify my assumptions of how the application was supposed to work.

When it came time to implement the feature, in true TDD fashion, I first asked myself, “how will I test this?” — that is, I wanted an exit strategy before I even started to think about how to implement the feature. In other words, how would I know when I was done?

So I wrote several more tests, and I was immediately confronted with the overzealousness of TDD: I had failing tests that would remain angry and contemptuous toward me until I implemented the feature sufficiently enough to get them to pass. But once that last test passed, I had a surprisingly satisfying feeling as I pushed away the keyboard and said to myself, “I guess I’m done”.

I have friends who practice TDD full time on a much larger project and it really seems to work for them. While I think TDD worked well for me in the situation, I still remain skeptical of it in larger settings — or for larger amounts of time.

My primary issue with TDD stems from my inability to think about two things at once: am I writing tests, or am I writing software? If I’m constantly thinking “how would I test this?” then I’m not thinking about what I’m even supposed to be doing. Often I need to burst out and write some code, try some experiments, refactor it, experiment some more, throw it away and start again, etc.

It’s not uncommon, during this process, to realize that the tests are now wrong or otherwise obsolete, and now I have to make the internal context switch to nurse them back to health, breaking the flow of what I was otherwise doing.

It makes more sense, I think, as a general rule of development, to test after things have stabilized.

I imagine tests being all these little yipping puppies nipping at the cuff of my pants when I’m trying to walk. Sure they’re cute and all, but sometimes I just want to walk at a brisk pace and these damn puppies are getting in my way!

JavaOne Reject

Sunday, March 15th, 2009

The JavaOne sessions for this year’s conference have been posted on-line. Notably absent from the content catalog (notably that is, if you are me, or my mother), are my submissions. Since I have no shame in sharing my failures as well as my non-failures on this blog, what follows is the body of the rejection email that I received:

————————————————-

Dear Mr. Anderson,

Thank you for your submission(s) to the JavaOne 2009 conference. We regret to inform you that your submissions “Windows ‘95 Tips and Tricks”, and “Configuring Eudora for Your AppleTalk Network” are not only several years too late, they additionally do not reflect the central message of the conference (we would have accepted, for example, “Configuring JavaFX for Your AppleTalk Network”).

While we appreciate the anti-Microsoft sentiment in your third submission, “Why Killzone 2 is some much more Awesome than Gears of War 2. Playstation Rulz!”, we feel that it would be better received at a more juvenile venue, such as the Apple Developer’s Conference.

We again thank you for your interest in presenting at JavaOne. It is presenters such as yourself that help make the conference a continued success from year to year (well, not specifically you obviously, but those like you that were selected).

A Critical (and Possibly Misinformed) Look at JavaFX Sequences

Wednesday, March 4th, 2009

Similar to the java.util.Collections utility class for the Collections API, javafx.util.Sequences is a utility class for Sequences. It contains, as expected, functions such for searching, sorting, general manipulation, and object lookup. This seems a bit split-brained to me though. 

Hang on. Hear me out.

I always felt that the Collections class was a concession to the limitation of the Java Programming language. Ideally it seemed, that functionality (or much of it) would have resided in the Collection interface, if Java would have allowed such a thing.

I don’t know how many times I tried to sort a List like this:

list.sort();

only be be quickly reminded by the compiler that it should be this:

Collections.sort(list);

So I’m a little surprised that a Sequences utility object exists at all. Why can’t I call “sort” and “indexOf” on a sequence directly? Since I can do this:

reverse s;

Why would I do this?

javafx.util.Sequences.reverse(s);

Actually I can’t do that. The compiler cryptically informs me that “You have missed out [sic] a part of the qualified name”.

Sorting seems to work though, but beware: Sequence immutability comes back to bite us. With Java, if I call:

Collection.sort(list);

it sorts the list I give it. If I call:

Sequences.sort(s);

it will not, of course, modify my original sequence. Ok, no problem:

s = Sequences.sort(s);

“Incompatible Types: found: java.lang.Comparable, required: Integer”

Doh.

s = Sequences.sort(s) as Integer[];

That’s quite a bit of syntax noise just to sort a sequence.

The language has many keywords for sequences: “insert”, “into”, “before”, “after”, “delete”, “sizeof”, “reverse”. Why not add “sort”, “contains”, “search”, etc?

Further, I think the fact that sequences are immutable should really be more of an implementation detail that I as a programmer shouldn’t have to care about. This is evidenced by the language level exceptions made for “insert” and “delete”.

insert 6 into s;
delete 6 from s;
delete s;

These operations all give the illusion of mutability. But the illusion breaks down here:

var s = [0..<5];

[ 0, 1, 2, 3, 4 ]

reverse s;

[ 0, 1, 2, 3, 4 ]

s = reverse s;

[ 4, 3, 2, 1, 0 ]

I don’t mind it one way or the other, but it seems that it should be consistent across all operations. Granted:

s = insert 6 into s;

would be really cumbersome. So I like the illusion of mutability, and further it seems that all operations should keep the illusion going, so that:

reverse s;

would actually, from my point of view, change “s”.  Similarly:

sort s;

would, again, regardless of any underlying immutability implementations, from the programmer’s point of view, sort “s” as if it were mutable.

I’m sure there are valid design reasons for things being the way they are, and since I put my foot in my mouth daily, I admit that, rather than these being valid criticisms, I simply don’t know what those reasons are.

Now that I’ve sufficiently backpedaled, thereby invalidating all the points that I’ve made, it’s time to end the post…

Staying on the Beat

Tuesday, March 3rd, 2009

Paul has written (and blogged about) a little piece of software that will analyze the tempo deviations of a song to try and determine whether or not the drummer used a click track. A click track is basically a metronome piped through headphones that can help the drummer (and therefore everyone else) stay on beat.

I asked Paul to analyze one of my band’s songs as a control (our drummer uses a click track). It turns out that our drummer is steady on the beat as compared to sloppy Metallica, but not as metronomic as Brittany Spears (that is, her drummer…or her drum machine).

Paul’s program is about 20 lines of Python code so it’s real power is in the Echo Nest remix API. There are actually a lot of things you can do with the Echo Nest Developer API. Stay tuned for a new JavaFX experiment that plugs into some of this power.