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.