Showing posts with label GWT. Show all posts
Showing posts with label GWT. Show all posts

Thursday, June 27, 2013

Show Me An Affinity

- Simplifying Complex Processing with a User Interface -

Every application I have ever worked on had the same end goal; provide useful, simple, easy to use and visually appealing screens.  Don't confuse me.  Don't make me click hundreds of times.  Don't leave important information out.  If something fails, tell me what to do next.

In designing a set of views and screens for my current project, the problem statement can be summarized as follows:
  • Show me where my applications are in my network
  • Let me pick the important applications and designate them as such
  • Let me define how these applications should be conversing
  • Do some SDN magic on these applications
  • Show me where my applications are in my ring
Providing the ability to see and do all of these actions requires a full application suite where common information is displayed from different perspectives.

In my Network view, I can search for specific virtual machines, among other things, and put them into an affinity group, thereby capturing the importance of an application in my network.





I am interested in how my three applications:
  • authhost71
  • authbox81
  • authclient62
converse with their backend databases dbserver28 and dbserver84. 



Everything in App1 talks with DB1, bidirectionally,  and I'd really like these conversations to be isolated from other ring traffic.

Is my ring ready for the SDN magic fitting algorithm to do it's thing?    Looks formed, healthy, good to go.



For each of my conversations, where are my applications traversing the ring?  My fitting results shows me how each application in App1 talks with each application in DB1; where it enters my ring, how it traverses my ring and where it exits my ring.





I found some applications in my network and after affinitizing them ("is that word? affinitizing?  it will be soon...."), I see clearly how my ring is handling their conversations and isolating them from all others. 

Taking a complex set of data and simplifying the ability to work with that data is what a good user interface is all about.   Show me an affinity? I saw an affinity today.





Friday, January 18, 2013

Fun with JIT, part1

Over the past year, I've been integrating JIT  (thejit.org) with my GWT application.  Javascript is not something for the faint of heart and personally I try to stay far away from it instead allowing  GWT to generate the Javascript for me based on my Java implementation code.  But to make use of, extend, and better control the canvas based layout tool JIT, I had to take on some Javascript.  So here's some things I did with it.  Any code snippets here should be considered pseudo-code and are for representation only.


Saving & Restoring Node Positions

The Force-Directed Graph has a built in layout algorithm that draws a graph as best as it can.  However, each time the graph is rendered, the layout algorithm produces a different layout.  We offer the user the ability to control the layout somewhat, specifying spacing between nodes and how many iterations the algorithm should use based on a complexity setting and some others:


Once the layout has been run, we then let the user drag the nodes and links around the screen to better position items to their liking.  To fully make this work, we need to save the node positions so that the next time we view the graph, we put all the nodes back into their original positions.  This also provides a big performance boost, in that we never run the layout algorithm a second time, but instead tell JIT where we want the nodes.

Save Positions:

// We store the node positions using our string object id, and the x,y values.
HashMap<String, ArrayList<Integer>> nodePositions;

// We iterate over the graph, getting the positions of each node.
mygraph.graph.eachNode(function(n) {
saveNodeData(n.id, Math.floor(n.getPos().x), Math.floor(n.getPos().y));
});

saveNodeData(String id, int x, int y)
{
    ArrayList<Integer> locations = new ArrayList<Integer>();
    locations.add(x);
    locations.add(y);
    nodePositions.put(id, locations);
}

Restore Positions:

// Lood our JSON data
nativeGraph.loadJSON(data);

// Put the nodes at the positions we want. No need to run the layout algorithm.

iterate over the saved node positions data and call this:
setNodePosition(JavaScriptObject nativeGraph, String id, int x, int y)
{
    node = nativeGraph.graph.getNode(id);
    if (node != null) {
        node.setPos(new $wnd.$jit.Complex(x,y), 'current');
        nativeGraph.plot();
    }
}


Resizing the Graph

JIT comes with some built-in functionality on many of their graphs that allows the user to scroll their mouse wheel which then causes the canvas to scale in and out, making the drawn objects grow or shrink.  I found this functionality to be somewhat difficult to control and also I wanted to control how large and how small I would allow the screen to scale to.  



I implemented two push buttons on my graph that allow the user to scale up or down as they are pressed.  One jumps 125% and the other jumps 80% which provides an even up/down scaling so that they user can always return to the default, 100%.

Scaling In:

Scaling in makes the objects larger.  Each time the user presses the "+" button, I ask JIT to:

nativeGraph.canvas.scale(1.25, 1.25);


Scaling Out:

Scaling out makes the objects smaller.  Each time the user presses the "-" button, I ask JIT to:

nativeGraph.canvas.scale(.8, .8);


Searching the Graph

Since my graph can get quite large with many of the objects off the edges of the viewable area, I implemented the ability to search for any node by name.  Once found, the node would be selected and the graph would be centered on the object, bringing the object into view for the user.  Here's how.


Find Node:

findNode(JavaScriptObject nativeGraph, String name)
{
    var p = new RegExp(name.replace("*", ".*"));
    
    nativeGraph.graph.eachNode(function(node) {
        if (p.test(node.name)) {
            // Found the node, we can get the x,y positions of this node.
    centerScreen(node.getPos().x, node.getPos().y);
}
}

centerScreen(String x, String y)
{
    // We are using a scroll panel with scroll bars as the parent of our JIT canvas
    // so we just adjust these scrollbars.
    graphContainer.setScrollLeft(((graphWidth / 2) -
(getOffsetWidth() / 2)) + x);
    graphContainer.setScrollTop(((graphHeight / 2) -
(getOffsetHeight() / 2) + y);
}

...More Fun with JIT, part2 coming soon.






Tuesday, September 4, 2012

Browsers, Browsers, Browsers

After several years of working with HTML, CSS and now GWT and Javascript, it has become quite clear that each browser is going to do things slightly different than others.  This just keeps the engineer on their toes; adds some danger to the mix; provides for some fun with borders and gradients and colors and buttons.

Here's some lessons I've learned recently in getting my GWT application to run across Safari, Chrome, Firefox, Internet Explorer and the Webkit mobile phone browsers.

1. Drawing on a canvas.  My application uses a third party javascript drawing package that uses a canvas for drawing elaborate diagrams.  This works great on all my browsers, except Internet Explorer. Nothing is drawn.  Alas, Internet Explorer doesn't have this native canvas built into it and must be given one.  In my main html file the addition of:

       <!--[if IE]><script language="javascript" type="text/javascript" src="excanvas.js"></script><![endif]-->

did the trick.

2. Right click popup menus.  Any right click you do in a browser produces the typical browser popup menu.  The one to View Source, or Open in New Window.  However, what about when I want to implement my own right click popups and put up my own menus.  In my main html file the addition of:


<body oncontextmenu = "return false;">


did the trick here too.  Now only my popup menus show up and nothing else.


3.  Gradients.  Those light to dark or dark to light backgrounds that make your screen really stand out and look slick.  The following displays a white to blue gradient and works on all browsers.


filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFF', endColorstr='#F3F7FB'); /* IE compatible */

background: -webkit-gradient(linear, left top, left bottom, from(#FFFFFF), to(#F3F7FB)); /* Webkit compatible */

background: -moz-linear-gradient(top,  #FFFFFF,  #F3F7FB); /* Firefox compatible */ 

4. Mobile phone.  Any browser based application, like GWT, should also run on all the mobile platform browsers by default.  But what if you application is just too big to fit nicely or to be useable on a mobile platform?  In this case, you should think about presenting the data in a different view on a mobile device as opposed to being on laptop/desktop computer with adequate screen real estate.  Here's two critical things I did to build a mobile version of my GWT app:

 First - how to detect if my application is trying to be run on Android or iPhone?

        // Is this an Android or iPhone device?
        if (Navigator.getUserAgent() != null)
        {
            if (Navigator.getUserAgent().toLowerCase().contains("android") ||
                Navigator.getUserAgent().toLowerCase().contains("iphone"))
            {
                mobileDevice = true;
            }
        }

Second - how to scale my view to fill the screen on the detect smartphone?

<meta name="viewport" content="width=device-width,initial-scale=1.0" />

Was added to my main html file.  In my case, rather than show my entire GWT application on a mobile device, I chose to show just a list of objects with the ability to touch each one and see more details.  Something simple, something usable, something informative, something that fits on the phone.

As I continue down the path of GWT....I'm sure there will be more browser tweaks needed...keeps me on my toes.

  


Friday, June 1, 2012

GWT - Flash - Swing [Lessons learned]

Approximately one year ago I joined a new startup company and had to decide what technology would be used to build a new highly graphical application.  The requirements were :

  • display dashboard pseudo realtime charts and tables
  • display graphs of objects and their associations and links
  • make it feel like a state of the art application with some coolness factor
  • make it usable and intuitive
  • make it scale
So I built some sample screens using Java Swing, the Google Web Toolkit and Adobe's Flash.  I was able to somewhat build the same screen using each of these technologies.  Long story short.....Java Swing was eliminated since we wanted to run in a web browser with no installation required.  Adobe Flash was eliminated since it would not run on various Apple devices and required a lot of specialization.  This left the Google Web Toolkit.  I had never used it, but had just come off learning Oracle's ADF Technology which actually has a lot in common.   Also, the development environment would be Java with Google doing the javascript generation for me. Being a Java Swing expert put me right in the driver's seat.  

- Advice to any Java Swing experts out there.....learn GWT.  It's a very easy transition. -

To get a jump, I bought the Essential GWT book and started reading and experimenting.  I also started reading and experimenting with the copious online documentation about GWT.  Turns out that the stackoverflow web site would prove extremely valuable for answering detailed technical questions.

My first task was to architect the directory structure and modeling for the application.  Using a MVP (Model, View, Presenter) model was the way to go.  This would allow me to later change the view code to use any widgets (maybe Droid stuff?) without changing the model or presenter code.  I may never do this with my application, but at least it's architected to get there someday.  In a nutshell, the View classes do the widget creation and layout.  The Presenter code handles all callbacks and handlers to push data to the widgets.  The Model code gets data from my db into data structures that I can access asynchronously using rpc AsyncCallback mechanisms.

Everything seemed to fall into place as the application was built.   A spot for images, dialogs, events, tables, panels and third party javascript integration was created.  At this point, any new feature is more of a cut and paste of an existing feature, which is exactly where a product starts to mature.  

I am very impressed with the GWT performance as well.  Drawing tables and charts and lists is very quick and efficient.  Integration with some javascript tools has been quite easy and reliable with the JSNI implementation.  CSS overriding of the GWT widgets has allowed me to completely brand the application to our company style and give it a sophisticated look and feel.  No gwt-ext or ext-gwt here.

Here's to releasing the product and showing some screen shots here soon....




Thursday, January 26, 2012

Steve Jobs Biography

For Christmas I received Steve Jobs biography. My family knows that I work in high tech and that I design user interfaces and applications and fell in love with my recent MacBook Pro, my first "Apple" product.

This is the first book that I've read cover to cover in quite a while. Most of my reading is technical articles, blogs, online books, etc. where I only have a few minutes to figure something out, learn a new technology or get an answer to a technical question.

As I went through the book, it became very nostalgic. I started my career in the early 80's at Digital...saw the first PC they made, saw a "color" screen appear and this thing called a mouse too. I look back now and feel so lucky that I was part of the user interface group, designing applications using DECWindows (and later Motif) and working with the User Interface lab, observing users and learning how someone interacts with a device. The whole interaction and experience is what has differentiated Apple from the beginning and was driven by Steve Jobs. Sure, they came up with great devices that did wonderful things and were so cool, but so did others, it was just that theirs were so elegant, simple and user friendly.

I look at the user interfaces I have designed and that I continue to design and I now have a more critical view of them. When a user lands on my screen, do they know what to do? Does it make sense? If they do the wrong thing, is it clear why that operation didn't work and what they should do instead? Do they need to read a manual to figure it out?

It is fascinating to me that since 1980 to now, 2012, UI design really hasn't changed at all. Buttons, menus, scrollbars, trees, tables, etc. are still the same. Just like an artist with a canvas and paint, it's the combination of colors, layout, textures that make his painting into art. Those who can take a complex set of data and a complex task and make into the most simple, logical, and easy operation end up with the most usable products.

I judge my applications by my users. How quickly are they doing productive work with it? Can I get them to the right screen with 1 click or 1 touch or 1 operation? Is my Product Manager out demoing and using the application without asking me anything about it? No one reads the manuals these days. The application has to "just work."

So today I work on user interfaces developed with GWT. I also design products for the Android interface. Any feature or layout or function I can imagine can be done with the GWT widget set. Any look or color or size or shape can be done with CSS. For Android, a smaller/touch screen presents a different set of challenges, but really forces me to think even simpler, more straightforward and work towards an elegant solution.

Steve Jobs was very demanding, knew what he wanted and would not be happy until he saw it and reading his biography has certainly left a mark on me. Steve thought something was total crap, horrible, unusable until one final tweak made it "perfect." So strive for quality - prototype - adjust - rework - open your eyes to the environment around you - and shape your work into something elegant. You are one tweak away from perfection.



Thursday, August 18, 2011

Internationalization/Localization From the Start

The title says it all. "...From the Start". Don't wait until someone wants to know if your application works with a foreign language to do the work. Retrofitting and removing strings etc. will drive you nuts and will be very unproductive. Instead, put the processes in place at the start so that your answer to their question is "Yes, of course, always has...". Here's some gory details on how, and how nice GWT is in doing the hard work for you:


Determining Locale


Before any of the following code examples will take affect, the system must know what locale it should be running against. This is done by adding the languages you support in your gwt.xml file. For example, to support English add:

<extend-property name="locale" values="en"/>


To add support for another language, say Spanish, add:


<extend-property name="locale” values="es”/>



To include the internationalization code into our Gwt application, we must add:
<inherits name="com.google.gwt.i18n.I18N”/> to our gwt.xml file.


The system will look at the locale running locally on the machine running our application and will tie that to the locale property. If the system sees “es” as the locale, then the application will automatically pick up the Spanish files. If we had created OurStrings.properties and OurStrings_es.properties, then the first file is used by default and the second is used if the locale matches “es”.





Internationalization


To implement an international scheme, we will use static string substitution to make the coding easier and to make the compiled javascript smaller and quicker. The process is as follows:


1. Create a properties file - AppMessages.properties, in the main client folder. This file has ids to strings such as

fileMenu = File

editMenu = Edit

helpMenu = help


2. Create a java interface class of the same naming - AppMessages.java in the main client folder. This file implements the properties file strings:


public interface AppMessages extends Messages
{
String fileMenu();

String editMenu();

String helpMenu();

}

there must be a method for each entry in the properties file.


3. In the main class that runs at startup, in the onModuleLoad() method, construct the class as:


AppMessage msgs = (AppMessages) GWT.create(AppMessages.class));


4. Now you can use the msgs class to find strings such as:


msgs.fileMenu(); which will return “File”.

msgs.editMenu(); which will return "Edit" and so on.



To pass parameters on strings, the properties file would have:
hello = hello {0}


The interface would be:
String hello(String who);


The call would be:
msgs.hello(“Eric”); which will return “hello Eric”.




Localization


Localization deals with the display of dates, times and numbers. Dates displayed in English using month/day/year are displayed differently in other countries, sometimes like day/month/year. So, 5/24/2001 in the US would be displayed as 24/5/2001 in England. Times should be displayed according to the timezone and numbers displayed according to the country formatting where decimal points and comma’s are sometimes intermixed. Gwt has automatic classes built in to support localization. Yes automatic. Based on the locale for the application, the dates, times, currencies will be translated for you:


Data today = new Date();
Wednesday Mar 23 12:11:44 UYT 2011


DateTimeFormat.getFullDateFormat().format(today);
Wednesday, March 23, 2011


DateTimeFormat.getFullTimeFormat().format(today);
12:11:44 PM Etc/GMT+3


There is also Long, Medium and Short formats as well.
DateTimeFormat.getShortDateFormat().format(today);
3/23/11
DataTimeFormat.getShortTimeFormat().format(today);
12:11 PM


For numeric displays, similar builtin Gwt classes are available:
double number = 22919.60;


NumberFormat.getDecimalFormat().format(number);
22,919.6


NumberFormat.getPercentFormat().format(number);
2,291,960%


NumberFormat.getCurrencyFormat().format(number);
$22,919.60


GWT does a lot for you here. There's no excuse to not take advantage of this. Yes, the world puts up with English software for sure, but the goodwill you get for having localized and internationalized applications might just get your company a lot more sales.


Monday, July 18, 2011

Everyone on the Bus

When doing UI development, we all know that we have to deal with callbacks. Callbacks when a mouse button is pressed, callbacks when the screen is resized, callbacks when a menu item is selected, callbacks for just about anything that can happen on your screen.

When designing a well structured piece of software, using object oriented techniques, we will end up with a nice hierarchy of classes, each with their own responsibilities and scope. Traditionally, we would build something like a menu class which handles all the menu creation and callbacks. For example, say someone picks the Help menu. This class gets the callback and launches the help system. But lets say that we want to put help buttons all over our application and give the user the option to get help on a variety of things. This would mean that the menu class would have to be passed around to all the other classes so that the various help buttons could trigger different help system displays. Or we could create one big master class that everyone has access to....but this begins to breakdown, means a lot of parameter passing and just starts to become spaghetti code. Not what we want to maintain.

So what is our option? The Event Bus, aka HandlerManager. What does this do you ask?
Quite simply, the event bus lets our client "fire" an event in one piece of code to be caught and handled by any other piece of code that is listening for this specific event.

Let's see some code. First we want to create an event and its handler. Lets use the help example. When fired, we want to create a help event with a string that will represent "what" help data we want to display.

HelpEventHandler.java:

public interface HelpEventHandler extends EventHandler

{
void onSelect(HelpEvent event);
}



HelpEvent.java:

public class HelpEvent extends GwtEvent

{
public static final Type TYPE = new Type();
private final String helpString;

public HelpEvent(final String helpString)
{
this.helpString = helpString;
}

@Override
protected void dispatch(final HelpEventHandler handler)
{
handler.onSelect(this);
}

@Override
public Type getAssociatedType()
{
return TYPE;
}


public String getHelpString()
{
return helpString;
}

}



We now have defined our event and a handler. Now we need someone to listen for this event as follows:

private final HandlerManager  eventBus   = new HandlerManager(null);


eventBus.addHandler(HelpEvent.TYPE, new HelpEventHandler()
{
@Override
public void onSelect(final HelpEvent event)
{
// Someone fired this event, do something with.
new HelpScreen(event.getHelpString()).show();
}
});




Lastly, we need someone to fire this event for the above listener to receive:

private final HandlerManager  eventBus   = new HandlerManager(null);

eventBus.fireEvent(new HelpEvent("my help topic"));


In summary, we built a specific event and handler. This event has a string as the data payload for it, a string that we use to go to a specific help page. This could be an object, data structure or any data that you want the event to get. We then setup a listener to act on this event being fired. Lastly, we fired the event. In practice, you can now implement a single listener and have lots of places in your code "fire" the event. You may have several places in your application where you want to show "help" and can build a single help display class while allowing any of your code to trigger it.

I've used this technique to allow for the editing of my objects from various places in my code. When someone initiates an edit operation, either from a menu pick, a right click, or by selecting on an object, the event is fired and my "edit object" code catches this request and puts up the edit dialog. I can get to this edit dialog from anywhere and never have to change my edit dialog code to do this.

I can now get to the edit dialog from anywhere in my code, just by Getting on the Bus.

Friday, July 1, 2011

Getting Started

As an experienced UI developer and designer, you know that you are going to need views, dialogs, menus, buttons, trees, tables, error dialogs, etc. You also know that you will want a nicely laid out directory structure to hold all your files and to establish a "place" for everything and everything in its "place". But where do you start... being new to GWT?

I started with a book. I chose Essential GWT - Building for the Web with Google Web Toolkit 2. My development platform is a Mac and my editor is the SpringSource Tool Suite (aka Eclipse). Starting with an example from the book, build your initial app and get it running. Spend some time modifying it and trying out different scenarios that the book covers. Learn about MVP (Model, View, Presenter) and adopt it to your liking. Understand how HTML + CSS and Java (compiled into javascript) will all fit together and will be used to make your application.

Make a change in Eclipse, save it and rebuild your app, then just refresh your browser and see how the changes automagically made it to your browser without stopping and restarting....very cool and will be so useful when you really get going.

As part of your initial design work, you will need to figure out what your app will be displaying and if you will need some 3rd party toolkits or if you want to go it natively with just the GWT basics? Native GWT will give you all the building blocks, but things like progress widgets, busy indicators, canvas renderers, etc. will not be there without bringing in some additional widgets. You may also want to bring in some Javascript widgets and integrate them, which is quite easy to do (a blog entry on that forthcoming).

Understand that you are on the web, in a browser, with a certain set of user expectations that are different that an installed application, but that line is blurring all the time.

I will be adding blog entries about GWT from here on out that provide specific small coding examples that answer "how do you do that?".

Monday, June 27, 2011

Welcome to GWT

After spending many years doing GUI development (starting with XWindows, DECwindows, then on to Motif and Java Swing) I was recently given the opportunity to move away from the application space and into the web space. "Build the same application you did with Swing, but make it web based" were the marching orders.

Now, I have to say that UI development seems to have not changed in 25 years. Yes, we got color, a mouse, animation, nicer fonts, etc. but we still create and manage widgets, think object oriented always, and need to put together layouts that adapt to screen sizes. Without even cracking a manual (actually a Google search now!) one can sit in Eclipse and pretty much guess what the method might be for doing something to a widget or for setting up a callback.

...Back to building my Swing app for the web. I was to use a technology called ADF (Oracle's Application Development Framework) with the end product deployed using Weblogic. Being a new Oracle employee, I had no prior knowledge of this technology and found not a lot in the internet about "how to" do things with it, so I decided why not share my findings as I went. My ADF blog was born. In very little time, I was able to start a new complete UI from scratch, taking advantage of templates, css styles, and a lot of code sharing. The complexity came in when trying to model and display data that was stored in our backend database that was "not" a typical RDB conforming data store, but that is a different story for a different day. Let's just say that where many web apps (and non-web apps) fall down is in building a multi-user, concurrent, auto refreshing application where all users coexist in harmony and life is good.

So now I've moved on to a very exciting new startup and was given free rain to "pick" the UI technologies that will be used. Slick, fast, usable, state of the art were the marching orders. After evaluating and comparing Swing, GWT and Flash, GWT was the winner. This blog will follow my adventure into GWT for the first time.

I knew nothing of XWindows/DECwindows and built DECplan, aka Microsoft Project before there was a Microsoft. Then on to Motif based NETarchitect integrated with an ObjectStore backend and is still the "fastest" performing application I have ever worked on. Next came a Swing based networking Control Center and a Virtualization Manager. Last was the ADF based Virtualization Manager and now a GWT set of applications.

I guess starting from drawing lines with X and building menu bars by hand has helped lead me on the path of making UI design and implementation "natural". I'm just wondering what will lead us into a new paradigm and really change the way Gui's are done. Maybe next lifetime.