Showing posts with label Plexxi GWT JIT Javascript. Show all posts
Showing posts with label Plexxi GWT JIT Javascript. Show all posts

Friday, March 15, 2013

Fun with JIT, part2

Here's some more neat things I've done with my GWT JIT integration.  The code snippets here are to represent what is possible and your mileage may vary.

Dragging Objects

In many of the JIT renderings, you can drag objects around the screen and can have full control over what you allow to be dragged.  You start by getting a callback when dragging is occurring:

onDragMove : function(node, eventInfo, e) {

where the "node" is the object that is being dragged and "eventInfo" has position information.  For a Force Directed JIT graph type, to allow dragging of your objects, you simply do this inside the onDragMove function:

var pos = eventInfo.getPos();
node.pos.setc(pos.x, pos.y);
fd.plot();

By the way, "fd" is an instance of the Force Directed graph.

As you drag the object around the screen, it will be moved and the graph will be replotted to show the update.  If the object you are dragging has any edges attached to it, they will automatically be moved as well.  But what if you have relationships on your display?  What if you have a parent object that has several children connected to it and when you drag the parent, you want the children to be dragged as well.  At Plexxi, we display a RING object with Plexxi Switches connected to the ring.  If a user drags our ring object, we want the switches to go with it.  Here's how:

onDragMove : function(node, eventInfo, e) {
    var pos = eventInfo.getPos();
    if (node.getData('type') == "plexxiring") {
        node.eachAdjacency(function(a) {
            childnode = fd.graph.getNode(a.nodeTo.id);
            childnode.pos.setc(childnode.getPos().x - (node.getPos().x - pos.x),
                                          childnode.getPos().y - (node.getPos().y - pos.y));
        });

    node.pos.setc(pos.x, pos.y);
    fd.plot();

What we do is get all the nodes connected to our dragged node and move them as well.  This performs surprisingly well in our application.  You can take this further and re-curse through all your objects moving even more when a single one is dragged.

Mouseover Tool Tips

On some occasions, you may want a tooltip or a text box to show up on the screen as the user moves the mouse over your nodes.  To insure good performance, you will want to add the tooltip text to a private JSON data object so that this text is instantly available to you at any time.  If you have to go back to your database of make some other calls to get your tooltip text, you may suffer from bad performance in rendering them. 

Here's how I did Tips with my Force Directed graph:

Tips : {
    enable : true,
    type : 'Native',
    offsetX : 10,
    offsetY : 10,
    onShow : function(tip, node) {
        tip.innerHTML = node.getData('tooltip');
   },


Auto Refreshing

One of the biggest issues with any graphical application is refreshing.  Does your user have to press a refresh button?  Does that waste time retrieving data from your database, destroying whatever you are currently displaying and rebuilding the display with new data? 

By using GWT and the built-in RPC mechanism, I am able to ask my GWT Server if any data has changed and then act of it.  This is a topic for another blog....but let's say my Force Directed graph is showing 5 different types of objects on it.  I ask the GWT Server to coordinate with my backend database to keep a cache of the objects I'm displaying and if any of these objects is modified, or deleted, let me know.  When I find out something that I am displaying has changed, then I take action.  The most common events are creating or deleting a link (edge), deleting an object or changing the name of an object.  Here's how they are handled as called by my GWT code:

private native void createLink(JavaScriptObject nativeGraph, String link, String from, String to)/*-{
        if (nativeGraph.graph.getAdjacence(from, to) == null) {
            var fromNode = nativeGraph.graph.getNode(from);
            var toNode = nativeGraph.graph.getNode(to);
            var adj = nativeGraph.graph.addAdjacence(fromNode, toNode,
                            {
                                'linkUuid' : link,
                                'selected' : 'false',
                                'linkcolor' : '#FF0000'
                            });
              
        nativeGraph.plot();
    }
}-*/;

private native void deleteLink(JavaScriptObject nativeGraph, String linkUuid)/*-{
        nativeGraph.graph.eachNode(function(n) {
            n.eachAdjacency(function(a) {
                if (a.data.linkUuid == linkUuid) {
                    a.setData('alpha', '0');
                    nativeGraph.graph.removeAdjacence(a.nodeFrom.id,
                            a.nodeTo.id);

                    nativeGraph.plot();
                    return;
                }
            });
        });
    }-*/;

private native void deleteNode(JavaScriptObject nativeGraph, String nodeUuid)/*-{
        nativeGraph.graph.eachNode(function(n) {
            if (n.id == nodeUuid) {
                n.setData('alpha', 0, 'end');
               nativeGraph.removeNode(nodeUuid, {
                     type: 'fade:seq'
                    duration: 1000, 
                    hideLabels: false 
                    transition: $jit.Trans.Quart.easeOut   
               });
            }
        });
 }-*/;


private native void updateNodeName(JavaScriptObject nativeGraph, String uuid, String newName)/*-{
        var node = nativeGraph.graph.getNode(uuid);
        if (node != null) {
            node.name = newName;
            nativeGraph.plot();
        }
}-*/;

fun with JIT part3 might be in the works......enjoy.





Tuesday, December 18, 2012

All Artists Need A Canvas

In designing user interfaces, the widgets provide the starting point.  The widget set typically includes lists, tables, trees, buttons, menus, and dialogs, and provides the interface designer with his tools.   Mapping data into a tree or a table, styling the widgets for a branded look and feel, adding scrolling, sorting, and selection behavior brings a user interface to life and provides the end user with instant visibility.

But sometimes these basic widgets don't go far enough with their ability to convey real world concepts. If a picture is truly worth a thousand words, a graphical four column table with rows of data does not a picture make.  So what alternatives are there?  What if I need to display objects arranged in a circular fashion with relationships between them?  What if I need to show a grab bag of elements that share various connections with each other?  How do I give the user that one picture worth a thousand words?

Given my requirements, I went searching for my etch-a-sketch that would both allow me to arrange objects and at the same time help me with the organization of them.  Enter JIT - Javascript InfoVis Toolkit.  A compact, simple, extendable and powerful canvas drawing and manipulation tool that could be easily integrated into my GWT-based application that was already underway.

In conjunction with the JIT documentation, examples and experts on the Google-groups, I was able to build a view that would provide our users with a visual rendition of network components and their connections between each other as shown.

Network View


We achieved support for:

  • Search by name with the resulting object being selected and centered on the screen
  • User draggable elements for user positioning or JIT auto layout algorithm activation
  • Saving of all element positions to redraw later using the same layout 
  • Zoom in and Zoom out functions for canvas scaling controlled with a "+" and "-" button press
  • Spacing between elements, canvas size, font size and name truncation controlled with view options
  • Full element selection, extended selection and right click popups for shortcut operations
  • Full link (or edge) selection, extended selection and right click popups for operations
  • Dynamic view refreshing using "sum" and "morph" JIT technologies via JSON data
  • Much more to come....

What about being able to show a set of objects related to each other in both directions?  A set of elements that form a ring?  Something that supports selection and can show elaborate connections, but that auto layouts the diagram perfectly each time?

Ring View




With the sunburst layout we achieved support for:

  • Search by name with the resulting object being selected on the screen 
  • Zoom in and Zoom out functions for canvas scaling controlled with a "+" and "-" button press
  • Ring size and spacing, font size and name truncation controlled with view options
  • Full element selection and right click popups for shortcut operations
  • Link (edge) highlighting using various colors based on search or selection criteria
  • Dynamic view refreshing
  • Much more to come....

By combining the asynchronous processing power and speed of GWT with a simple javascript canvas drawing and manipulation tool, we are well on our way to building an interface that fills trees, tables, buttons, menus and dialogs and provides that thousand word picture.