Monday, April 19, 2010

The Structure of GWT Applications

When building an application from scratch, using a personally new technology, I don’t know about you, but for me I often get lost in the bewildering maze of application setup.  How do I separate the client from server, I want to create widgets where do they go, How do I control event flow and listening?  As I was progressing through GWT this was beginning to hurt, then I decided to “Read the Instructions”. 

In the GWT SDK Google has provided a demo application called GWT Demo Showcase.  Not only does it show off all the visual components of the GWT architecture, it also provides a useful application template.  It is this application that I would like to briefly discuss today.

The Google GWT Demo Application

image The demo shows off many important features.  It completes two very important objectives.  Firstly, it shows us the capabilities of GWT.  All components are selectable and useable in a runtime mode from the left hand menu.  Secondly, it gives a great example of application architecture, which I would like to focus on here.

Project Structure

The package hierarchy, shown below, illustrates an important feature of the application and is a joy for developers to be able to implement strict control and organisation over their web applications.

image

Application Entry Point

/GWTDemoShowcase/src/com/google/gwt/sample/showcase/client/Showcase.java

This file contains the main application entry point, stores application level variables, and acts as a conduit for events in the application.  Once a decision has been made on how the application should look and which widgets should be shown either initially or as a result of application flow a call is made to the application instance of the Application class:

private Application app = new Application();


The declaration to change the visuals is along the lines of:



  private void displayContentWidget(ContentWidget content) {
if (content != null) {
app.setContent(content);
app.setContentTitle(content.getTabBar());
}
}


For a developer this information is priceless.  Or perhaps it is my naiveté at seeing coding down right.  There is a clear separation of classes and their purpose.  A joy to see!



Application Class



The application class controls the main look of the application and receives instructions routed via the main Showcase instance.  I don’t want to go into too much detail here because the class is pretty self explanatory with methods like setTite, setContent etc.  I think it is important to know however how the initial setup of a widget occurs.



Display widgets are associated with menu options using a HashMap in the Showcase instance.  When a menu event occurs this fires in Showcase and the widget associated is retrieved from the HashMap.



    // Add a handler that sets the content widget when a menu item is selected
app.addSelectionHandler(new SelectionHandler<TreeItem>() {
public void onSelection(SelectionEvent<TreeItem> event) {
TreeItem item = event.getSelectedItem();
ContentWidget content = itemWidgets.get(item);
if (content != null && !content.equals(app.getContent())) {
History.newItem(getContentWidgetToken(content));
}
}
});



In this code a new tree selection is made and the widget extracted from the HashMap.  Finally a new event is added to the History object.  This is all very well but where is the call to the “app” instance to change the look of the application.  We take a look just above this code and it becomes self evident.



    // Setup a history handler to reselect the associate menu item
final ValueChangeHandler<String> historyHandler = new ValueChangeHandler<String>() {
public void onValueChange(ValueChangeEvent<String> event) {
TreeItem item = itemTokens.get(event.getValue());
if (item == null) {
item = app.getMainMenu().getItem(0).getChild(0);
}

// Select the associated TreeItem
app.getMainMenu().setSelectedItem(item, false);
app.getMainMenu().ensureSelectedItemVisible();

// Show the associated ContentWidget
displayContentWidget(itemWidgets.get(item));
}
};
History.addValueChangeHandler(historyHandler);



Widget SEtUP and the HashMap



In this application a HashMap is set up associating Nodes on the tree select sidebar with the content widgets for the main area.  This is constructed on page initialization within the



private void setupMainMenu(ShowcaseConstants constants) {
Tree mainMenu = app.getMainMenu();

// Widgets
TreeItem catWidgets = mainMenu.addItem(constants.categoryWidgets());
setupMainMenuOption(catWidgets, new CwCheckBox(constants),
images.catWidgets());
setupMainMenuOption(catWidgets, new CwRadioButton(constants),
images.catWidgets());
setupMainMenuOption(catWidgets, new CwBasicButton(constants),
images.catWidgets());
....



Which calls setupMainMenuOption:



  private void setupMainMenuOption(TreeItem parent, ContentWidget content,
ImageResource image) {
// Create the TreeItem
TreeItem option = parent.addItem(AbstractImagePrototype.create(image).getHTML()
+ " " + content.getName());

// Map the item to its history token and content widget
itemWidgets.put(option, content);
itemTokens.put(getContentWidgetToken(content), option);
}



Summary



I love this demo project.  If you are considering building a GWT application it would be worthwhile to take a quick look at it.  Whilst it doesn’t implement a MVC architecture, which depending on your preference you might prefer, it does offer a good starting point.



No comments:

Post a Comment