December 26, 2008

Sapphire is out

Filed under: JavaFX — Ben Jones @ 10:40 am

Seems that the Blogosphere is interested in Sapphire. Since Jim Weaver posted his first blog regarding Sapphire, it has been carried over to DZone, then into JavaLobby, then out to several other technology blogs and now has landed as an item of interest on the Sun Microsystems front page.

Thanks everyone for your interest and commentary on this JavaFX application. Below is a snapshot of the Sun page. Please head on over to Sun and express your support for JavaFX.

Sun site inclusion

December 20, 2008

A brief charting example

Filed under: JavaFX — Ben Jones @ 10:21 pm

This is the technical writeup I provided to Jim Weaver for his updated blog with some editorial changes.

One of the features of JavaFX that makes it attractive to real-time application developers is its ability to tie graphical elements to models through the binding mechanism. This mechanism makes it possible for the current state of the model to be reflected in the interface without the need to create any type of polling system.

In our Sapphire application, we collect real-time data from classroom observations. The observer records classroom events by pressing various buttons. These events are displayed in several dashboard type displays which are actively tied to supporting models. One of these displays in a time lime of events created by a series of colored rectangles. The size, placement and color of the rectangles represent different relationships in the event data. Every time an event is pressed, the data changes and the bound display automatically updates.

To achieve this, you only need three things: a data model, a display element, and an event driver of some type. Let’s take a look at one of the visual building blocks, the TimeOnTaskBlock class:

public class TimeOnTaskBlock extends CustomNode {

public var aboveColor:Color = Color.GREEN;
public var belowColor:Color = Color.RED;

public var seconds:Integer;
public var startingMark:Integer;
public var zoneWidth:Integer = 600;
public var zoneSeconds:Integer = 3600;
public var height:Integer = 100;
public var maxSegments:Number = 5;
public var segment:Number = 0;
public var x:Integer;
public var scale:Number = 0.95;

  public override function create(): Node {
    return Group {

      var maxDisplayHeight:Number = height/2;

      content: [
        Rectangle {
          x: bind zoneWidth * startingMark / zoneSeconds;
          y: bind height/2 - scale * ((maxDisplayHeight) * segment/maxSegments)
          width: bind zoneWidth * seconds / zoneSeconds;
          height: bind scale * (maxDisplayHeight * segment/maxSegments)
          fill: bind aboveColor
          strokeWidth:0
        },
        Rectangle {
          x: bind zoneWidth * startingMark / zoneSeconds;
          y: bind height / 2
          width: bind zoneWidth * seconds / zoneSeconds;
          height: bind scale * (maxDisplayHeight - (maxDisplayHeight * segment/maxSegments))
          fill: bind belowColor
          strokeWidth:0
        }
      ]
      effect: Lighting {
        light: DistantLight { azimuth: 225 elevation: 60 }
        surfaceScale: 2
      }
    };
  }
}

This custom node represents what will be displayed. It is a pair of scaled rectangles stacked on top of each other. The various attributes define shape, size, and placement. Notice the use of the the DistantLight effect to give the rectangles in the graph some depth. The next building block up from this is another custom node that handles the visual orchestration of the time blocks nodes. The DisplayTimeChart node is effectively the dashboard element being displayed. It has a data member holding a sequence of TimeOnTaskBlock nodes. Let’s take a peek at this node:

public class TimeOnTaskBlock extends CustomNode {

public var aboveColor:Color = Color.GREEN;
public var belowColor:Color = Color.RED;

public var seconds:Integer;
public var startingMark:Integer;
public var zoneWidth:Integer = 600;
public var zoneSeconds:Integer = 3600;
public var height:Integer = 100;
public var maxSegments:Number = 5;
public var segment:Number = 0;
public var x:Integer;
public var scale:Number = 0.95;

  public override function create(): Node {
    return Group {

      var maxDisplayHeight:Number = height/2;

      content: [
        Rectangle {
          x: bind zoneWidth * startingMark / zoneSeconds;
          y: bind height/2 - scale * ((maxDisplayHeight) * segment/maxSegments)
          width: bind zoneWidth * seconds / zoneSeconds;
          height: bind scale * (maxDisplayHeight * segment/maxSegments)
          fill: bind aboveColor
          strokeWidth:0
        },
        Rectangle {
          x: bind zoneWidth * startingMark / zoneSeconds;
          y: bind height / 2
          width: bind zoneWidth * seconds / zoneSeconds;
          height: bind scale * (maxDisplayHeight - (maxDisplayHeight * segment/maxSegments))
          fill: bind belowColor
          strokeWidth:0
        }
      ]
      effect: Lighting {
        light: DistantLight { azimuth: 225 elevation: 60 }
        surfaceScale: 2
      }
    };
  }
}

The TimeDisplayChart serves a couple of purposes. First it builds the overall dashboard element. This defines the usual display space, necessary labeling and element placements. Please note two aspects of this class: the group where its content is bound to the displayBlocks sequence and the second group composed of a solo TimeOnTaskBlock. By binding the content of a group to a data source, any changes in the data source will be made available to the group automatically. This effectively produces a self-updating display since we bound a displayable node. The second group which is a single instance of the TimeOnTaskBlock serves another purpose. It covers the span of time since the last data change and the current time. Since the data model stores only past events, we need a means of showing data yet to be stored. It’s real-time after all.

To place all of this into an application, an instance of TimeDisplayChart is placed into a group as follows:

Group {
  translateY:310
  translateX:10
  content:[
    TimeDisplayChart{
      width:600
      height:100
      zoneSeconds:3600
      zoneWidth:600
      background:Color.#969696
      timer: bind timer
      displayTicker: bind displayTicker
      currentSegment: bind appState.currentSegment
      timeMark: bind appState.currentTimeMark
      onColor: bind appState.onColor
      offColor:bind appState.offColor
      displayBlocks: bind displayblocks
    }
  ]
}

Here we can see the various attributes of the custom node being bound to different data sources and conditions that exit within the larger context of the application. The bindings create an active communication channel between application state data and the graphical elements. It’s convenient, responsive, and easy to manage during the development process.

You can find a wealth of information about JavaFX and what people are doing with this RIA technology over at Jim Weaver’s JavaFX blog and of course at Sun’s JavaFX.

December 18, 2008

Sapphire in the Wild!

Filed under: JavaFX — Ben Jones @ 6:59 pm

Sapphire, the classroom observation tool, has hit the web for its public debut. Written in the newly released official JavaFX 1.0 from Sun Microsystems,  Sapphire brings advanced Rich Internet Application technology to educators focused on observing classrooms. The Community Edition which is available from our website was featured by the prominent JavaFX blogger and author Jim Weaver. Check out the JavaLobby posting at JavaFX in the wild.

Thank you Jim Weaver for your interests in our JavaFX endeavors.

Powered by WordPress