Tag Archives: clock

A Case Study: A JavaFX Widget Framework API

A prototype of a widget container

A prototype of a widget container

Building a better mousetrap

In short I want to revisit the idea of a cross platform widget framework using JavaFX. In this article I’d like to share some ideas, concepts and prototypes that might invigorate this old but ingenious idea for the desktop and embedded world. An old idea you say? Does anyone remember WidgetFX?

In the early days of JavaFX there were a few Java Champions and community members who decided to create a cross platform JavaFX 1.x widget framework for the desktop (year 2008). I was fortunate enough to know many of those contributors involved.  I grew to love the capabilities the framework and widgets were able to provide.  However, as we all know JavaFX is now redone as Java APIs as opposed to the JavaFX script language. This eventually became apparent regarding to the future of most frameworks back then. Before I begin I would like to give credit to the folks who contributed to the WidgetFX framework project.  I want to thank them for their enthusiasm and their tireless efforts on building the community to what it is today. To see some of their cool widgets please visit the site http://widgetfx.org (catch them before they’re gone). Two of the original founders of the project are Stephen Chin and Keith Combs. Even though I did not partake in the fun during the height of the project I was quite inspired.

Inception phase

To fast forward just last year at the JavaOne 2012 conference I was able to catch up with Keith Combs (Silicon Valley JavaFX User Group organizer) and Stephen Chin (Java Technology Evangelist at Oracle) after his keynote speaking to inquire about the WidgetFX project now that JavaFX 1.x is no more. Steve kindly asked if anyone would be interested in giving it a reboot on the JavaFX 2.x platform (As he peered over towards Keith and me). I believe I said, “I don’t think, so… “. I thought it might be too much to bite off than I could possibly chew. So I politely declined the offer. During the conference I was later enamored by all things Java embedded which later fueled to some of my home automation project ideas using JavaFX with (Arduino, Raspberry Pi, and Beagle Board).

After returning home I was not only excited about the things I’ve learned at the conference but, I also was in the middle of transitioning to a new job and company. Working as a UI and Visualization developer for cloud based monitoring software I often encountered stakeholders/SMEs mentioning the term “SPOG” or single pane of glass.

What does the term “SPOG” mean?

According to Floyd Strimling a cloud technical evangelist at Zenoss explains how so many organizations will create desperate (silos) systems and he goes on to say, “The Holy Grail is a single pane of glass that provides IT managers with a single access point to make sense of their entire underlying infrastructure in real time”. (Searching for the Mythical Single Pane of Glass)

Isn’t “SPOG” an interesting concept for large operation centers? So, I continued to rethink of the old idea of a flexible widget framework that would provide richer interfaces that would allow better desktop integration, decoupled services, higher performance, and capable of empowering users with many of the modern UI metaphors that they’d expect on their favorite OS platform. I believe such a framework should also work on embedded devices for home automation.  Actually I got the idea of a widget framework for embedded devices from my good friend Gerrit Grunwald (Java Champion and author of the popular Steel Series API) while exchanging ideas about graphics performance and launching JavaFX applications on embedded devices.

Wow, with so many different problem domains and so many perspectives could such a widget framework truly exist? Could such a widget framework be able to make everyone happy? Is it possible to create a simple widget framework to rule them all? I believe it is possible.

eWidgetFX is born

In the back of my mind I noticed similar use cases with many customers wanting widget frameworks having this concept of a “SPOG”, but also provide a framework that I could use myself on my own desktop or touch device. So, I kept going back and forth on the possibility of rebooting the old project WidgetFX. Instead I wanted to throw a monkey wrench into the whole business of widget frameworks. Since there are so many kinds of ways to launch, display, and manage widgets it would also be a good idea to build a single widget framework SPI (service provider interface API) which would enable developers to build their own widget containers thus allowing widget developers to run their widgets in any widget container. There would basically be two developer perspectives: Container Developers and Widget Developers. So, I’d like to propose a new API called eWidgetFX (core) that would allow the developers to create widget containers and widgets.

For now I will defer the work of designing the core APIs and make it a future post. So, in this article I’ve decided to generate some prototypes of widget containers that would basically depend on the future eWidgetFX framework API.

Prototyping Widget Containers

Prototyping is probably the most fun part during any software development activity. Shown below are videos I recently uploaded to Youtube.com to kick some ideas around for different kinds of widget containers (Icon App tray) on a desktop environment.

Conclusion

One of the main issue I found in UI development is that customers will often know what they want, but aren’t able to communicate what they ultimately want. It’s almost like playing a game of Charades or a game of Pictionary where guessing is a sought after skill in software design.  We are often faced with providing prototypes and end up settling on one particular view (one view, one way, one silo). The problem became pretty apparent where everyone had an opinion or philosophical stance on a particular GUI interface, usability aspect or UI metaphor. Sometimes it’s based on subjective personal preferences that can go into long discussions. No one person in the room was completely happy, but at the end of the day we compromised and we settled.

I believe that by creating a widget API it would allow organizations to build different single pane of glass instances (widget containers) and capable of sharing all widgets across other panes.

So, imagine seeing different types of widget containers in the wild. Some future widget containers could look like interfaces similar to the following movies: Avengers, Tron, or Minority Report

A final note: Many of of the ideas expressed and proposed are a collective effort from some of my friends (team members) of the JFXtras.org project (Mark Heckler, Hendrik Ebbers, and Gerrit Grunwald).

Would you like to see a talk regarding widget frameworks at JavaOne?

As always comments are welcome.

Carl 😉

Resources

JavaFX: http://www.oracle.com/technetwork/java/javafx/overview/index.html
Java Champions: https://java.net/website/java-champions/bios.html
WidgetFX: http://widgetfx.org
Keith Combs from the Silicon Valley JavaFX user group: http://www.svjugfx.org/member/10394895/?op=&memberId=10394895
Steve on Java by Stephen Chin: http://steveonjava.com
Arduino : http://www.arduino.cc
Raspberry Pi: http://www.raspberrypi.org
Beagle Board: http://beagleboard.org
Guest Post: Searching for the Mythical Single Pane of Glass: http://siliconangle.com/blog/2012/02/29/guest-post-searching-for-the-mythical-single-pane-of-glass
Anti-patterns: http://en.wikibooks.org/wiki/Introduction_to_Software_Engineering/Architecture/Anti-Patterns
Google Images of Operation centers: http://bit.ly/106p3h0
Avengers UI design: http://cargocollective.com/jayse/Avengers
Tron UI design: http://dlew.me/Tron-Legacy-Boardroom
Minority Report UI designer demos his tech at TED (video): http://www.engadget.com/2010/06/03/minority-report-ui-designer-demos-his-tech-at-ted
The Java Jungle by Mark Heckler: https://blogs.oracle.com/javajungle/entry/welcome_to_the_jungle
Gui Garage by Hendrik Ebbers: http://www.guigarage.com
Harmonic Code by Gerrit Grunwald: http://harmoniccode.blogspot.de
JFXtras.org : http://jfxtras.orgLeap Motion: https://www.leapmotion.comLeap Motion: https://www.leapmotion.com

30 Lines of JavaFX Coding Challenge Theme – Time

Space Time (updated!)

My entry is called ‘Space Time‘. A 3D cube clock. The full source code that is readable is below the article.

Wow, it is amazing at what you can you do in 30 lines of JavaFX code or 3000 characters.   JFXStudio is running a contest and the theme has to do with “TIME”. Although I posted my entry very last minute, there will be other chances for you to enter. Please visit http://jfxstudio.wordpress.com/2009/08/31/jfxstudio-challenge-small-is-the-new-big/

Space Time

Space Time

My entry including the import statements are just at 30 lines with each line containing less than or equal to 100 characters.  Click on the image to launch the demo.

Instructions:

  • Observe the cube rotating as each tick a second.
  • Observe the Space Time Title’s Distant lighting effect as seconds go by
  • Use mouse drag to rotate 3D cube
  • import javafx.animation.*;import javafx.scene.*;import javafx.scene.paint.Color;import javafx.scene
    .effect.*;import javafx.scene.text.*;import javafx.scene.shape.*;import javafx.scene.input.
    MouseEvent;import javafx.util.Math;class P{var x:Number;var y:Number;var z:Number;var sX:Number;var
    sY:Number;}class E{var a:Integer;var b:Integer;}var w:Number=800;var h:Number=600;var a:Number=30;
    var e:Number=30;var vs:P[]=[];function av(x:Integer,y:Integer,z:Integer){insert P{x:x,y:y,z:z}into
    vs;}av(-1,-1,-1);av(-1,-1,1);av(-1,1,-1);av(-1,1,1);av(1,-1,-1);av(1,-1,1);av(1,1,-1);av(1,1,1);var
    es:E[]=[];function aE(a:Integer,b:Integer){insert E{a:a,b:b}into es;}aE(0,1);aE(0,2);aE(0,4);aE(1,3
    );aE(1,5);aE(2,3);aE(2,6);aE(3,7);aE(4,5);aE(4,6);aE(5,7);aE(6,7);var ps:Circle[]=[];var ls:Line[]=
    [];function mps(c:Boolean):Void{var th:Number=bind 0.017453*a;var ph=0.017453*e;var cT=Math.cos(th)
    ;var sT=Math.sin(th);var cP=Math.cos(ph);var sP=Math.sin(ph);var cTcP=cT*cP;var cTsP=cT*sP;var sTcP
    =sT*cP;var sTsP=sT*sP;var sf=bind w/4;for(i in[0..sizeof vs-1]){var x0=vs[i].x;var y0=vs[i].y;var
    z0=vs[i].z;var x1=cT*x0+sT*z0;var y1=-sTsP*x0+cP*y0+cTsP*z0;var z1=cTcP*z0-sTcP*x0-sP*y0;x1=x1*3/(
    z1+4.5);y1=y1*3/(z1+4.5);vs[i].sX=x1;vs[i].sY=y1;if(c)insert Circle{centerX:bind w/2+sf*vs[i].sX+.5
    ,centerY: bind h/2-sf*vs[i].sY+.5,radius:2 fill:Color.BLUE}into ps;}if(c)for(e in es){insert Line{
    startX:bind ps[e.a].centerX startY:bind ps[e.a].centerY endX:bind ps[e.b].centerX endY:bind ps[e.b]
    .centerY strokeWidth:2,stroke:Color.BLUE}into ls;}}mps(true);var mx:Number;var my:Number;var g:
    Rectangle=Rectangle{x:0,y:0 width:bind w,height:bind h fill:Color.BLACK onMousePressed:function(me:
    MouseEvent):Void{mx=me.x;my=me.y;}onMouseDragged:function(me:MouseEvent):Void{var new_mx=me.x;a-=
    new_mx-mx;var new_my=me.y;e+=new_my-my;mx=new_mx;my=new_my;mps(false);}}var ct:String=new java.util
    .Date().toString();var tz:Integer=-125;var t=Group{content:[Text{effect:Lighting{light:javafx.scene
    .effect.light.DistantLight{azimuth:bind tz elevation:40}surfaceScale:5} x:10 y:50 content:"Space "
    "Time" fill:Color.RED font:Font{name:"Arial Bold" letterSpacing:0.20 size:50}},Text{x:10 y:80
    content:bind ct fill:Color.BLUE font:Font{name:"Arial Bold" letterSpacing:0.20 size:20}}]}var bc=
    Group{content:[Rectangle{x:10,y:bind h-85,arcHeight:5,arcWidth:5,width:bind w-30,height:30,fill:
    Color.RED,opacity:.5},Text{effect:DropShadow{offsetX:10,offsetY:10,color:Color.BLACK,radius:10}
    opacity:.5 x:15,y:bind h-65,content:"by Carl Dea - carlfx.wordpress.com"fill:Color.WHITE font:Font{
    name:"Arial Bold"letterSpacing:.20 size:20}}]}var scene:Scene=Scene{content:bind[g,ps,ls,t,bc]};var
    anim=Timeline{keyFrames:[KeyFrame{time:1s action:function():Void{a-=1;mps(false);ct=new java.util.
    Date().toString();if(tz>125){tz=-125;}tz+=2;}}]repeatCount:Timeline.INDEFINITE};anim.play();javafx.
    stage.Stage{width:bind w with inverse height:bind h with inverse scene:scene}

    Enjoy!
    Please vote for me…
    Let me know what you think. 🙂

    Here is the readable source code below:

    /**
     * Main.fx
     * 
     * Check out http://www.comp.brad.ac.uk/research/GIP/tutorials/project1.html 
     * for all the math.
     * Created on Dec 20, 2009, 11:06:15 PM
     */
    
    package bigsmall.part8;
    
    import javafx.animation.*;
    import javafx.scene.*;
    import javafx.scene.paint.Color;
    import javafx.scene.effect.*;
    import javafx.scene.effect.light.DistantLight;
    import javafx.scene.text.*;
    import javafx.scene.shape.*;
    import javafx.scene.input.MouseEvent;
    import javafx.stage.*;
    import java.util.Date;
    import javafx.util.Math;
    
    class Point3D {
       var x: Number;
       var y: Number;
       var z: Number;
       var screenX: Number;
       var screenY: Number;
    }
    
    class Edge {
       var a: Integer;
       var b: Integer;
    }
    var width: Number = 800;
    var height: Number = 600;
    var azimuth: Number = 30;
    var elevation: Number = 30;
    var vertices: Point3D[] = [];
    
    function addVertex(x: Integer, y: Integer, z: Integer) {
       insert 
          Point3D {
             x: x, 
             y: y, 
             z: z
          } 
       into vertices;
    }
    
    addVertex(-1, -1, -1);
    addVertex(-1, -1, 1);
    addVertex(-1, 1, -1);
    addVertex(-1, 1, 1);
    addVertex(1, -1, -1);
    addVertex(1, -1, 1);
    addVertex(1, 1, -1);
    addVertex(1, 1, 1);
    
    var edges: Edge[] = [];
    
    function addEdge(a: Integer, b: Integer) {
       insert 
          Edge {
             a: a, 
             b: b
          } 
       into edges;
    }
    
    addEdge(0, 1);
    addEdge(0, 2);
    addEdge(0, 4);
    addEdge(1, 3);
    addEdge(1, 5);
    addEdge(2, 3);
    addEdge(2, 6);
    addEdge(3, 7);
    addEdge(4, 5);
    addEdge(4, 6);
    addEdge(5, 7);
    addEdge(6, 7);
    
    var points: Circle[] = [];
    var lines: Line[] = [];
    
    function movePoints(createFirstTime: Boolean): Void {
       var theta: Number = bind 0.017453 * azimuth;
       var phi = 0.017453 * elevation;
       var cosTheta = Math.cos(theta);
       var sinTheta = Math.sin(theta);
       var cosPhi = Math.cos(phi);
       var sinPhi = Math.sin(phi);
       var cosThetaCosPhi = cosTheta * cosPhi;
       var cosThetaSinPhi = cosTheta * sinPhi;
       var sinThetaCosPhi = sinTheta * cosPhi;
       var sinThetaSinPhi = sinTheta * sinPhi;
       var scaleFactor = bind width / 4;
       for (i in [0..sizeof vertices - 1]) {
          var x0 = vertices[i].x;
          var y0 = vertices[i].y;
          var z0 = vertices[i].z;
          var x1 = cosTheta * x0 + sinTheta * z0;
          var y1 = -sinThetaSinPhi * x0 + cosPhi * y0 + cosThetaSinPhi * z0;
          var z1 = cosThetaCosPhi * z0 - sinThetaCosPhi * x0 - sinPhi * y0;
          x1 = x1 * 3 / (z1 + 4.5);
          y1 = y1 * 3 / (z1 + 4.5);
          vertices[i].screenX = x1;
          vertices[i].screenY = y1;
          if (createFirstTime) {
             insert 
                Circle { 
                   centerX: bind width / 2 + scaleFactor * vertices[i].screenX + 0.5,
                   centerY: bind height / 2 - scaleFactor * vertices[i].screenY + 0.5,
                   radius: 2 
                   fill: Color.BLUE
                } 
             into points;
          }
       }
    
       if (createFirstTime) {
          for (edge in edges) {
             insert 
             Line {   
                startX: bind points[edge.a].centerX
                startY: bind points[edge.a].centerY
                endX: bind points[edge.b].centerX
                endY: bind points[edge.b].centerY
                strokeWidth: 2,
                stroke: Color.BLUE
             } 
             into lines;
          }
       }
    }
    
    // create the first time; draw cube.
    movePoints(true);
    
    var mouseX: Number;
    var mouseY: Number;
    
    // Space region that changes the azimuth and recalculates the cube 
    var galaxy: Rectangle = Rectangle { 
       x: 0,
       y: 0
       width: bind width,
       height: bind height
       fill: Color.BLACK
       onMousePressed: function (me: MouseEvent): Void {
          mouseX = me.x;
          mouseY = me.y;
       }
       onMouseDragged: function (me: MouseEvent): Void {
          var new_mx = me.x;
          azimuth -= new_mx - mouseX;
          var new_my = me.y;
          elevation += new_my - mouseY;
          mouseX = new_mx;
          mouseY = new_my;
          movePoints(false);
       }
    } // galaxy
    
    var currentTime: String = new Date().toString();
    var initialAzimuth: Integer = -125;
    
    // Title with current time seconds.
    var titleDisplay = Group { 
       content: [
          Text {    
             effect: Lighting {  
                light: DistantLight {
                   azimuth: bind initialAzimuth
                   elevation: 40
                }
                surfaceScale: 5
             }
             x: 10
             y: 50
             content: "Space Time"
             fill: Color.RED
             font: Font {    
                name: "Arial Bold"
                letterSpacing: 0.20
                size: 50
             }
          },
          Text {    
             x: 10
             y: 80
             content: bind currentTime
             fill: Color.BLUE
             font: Font {    
                name: "Arial Bold"
                letterSpacing: 0.20
                size: 20
             }
          }
       ]
    }; // titleDisplay Group
    
    
    // This is the bottom display credits
    var byCarl = Group {    
       content: [
          Rectangle {   
             x: 10,
             y: bind height - 85,
             arcHeight: 5,
             arcWidth: 5,
             width: bind width - 30,
             height: 30,
             fill: Color.RED,
             opacity: .5
          },
          Text {    
             effect: DropShadow {    
                offsetX: 10,
                offsetY: 10,
                color: Color.BLACK,
                radius: 10
             }
             opacity: .5
             x: 15,
             y: bind height - 65,
             content: "by Carl Dea - carlfx.wordpress.com"
             fill: Color.WHITE
             font: Font {
                name: "Arial Bold"
                letterSpacing: .20
                size: 20
             }
          }
       ] // byCarl contents Group
    }; // by Carl
    
    var scene: Scene = Scene {  
       content: bind [
          galaxy, 
          points, 
          lines, 
          titleDisplay, 
          byCarl]
    };
    
    // this is the ticking motion of the cube.
    var anim = Timeline {   
       keyFrames: [
          KeyFrame {
             time: 1s
             action: function (): Void {
                azimuth -= 1;
                movePoints(false);
                currentTime = new Date().toString();
                if (initialAzimuth > 125) {
                  initialAzimuth = -125;
                }
                initialAzimuth += 2;
             }
          }
       ] // keyFrames
       repeatCount: Timeline.INDEFINITE
    }; // animation
    
    anim.play();
    
    Stage { 
       title: "Space Time"
       width: bind width with inverse
       height: bind height with inverse
       scene: scene
    }