Enterprise Java

Advanced SmartGWT Tutorial, Part 1

Justin, Pat and I have started working on a side project that requires a user interface for administration and management. After working for a while with SmartGWT and GWT in general, we decided to create the interface using SmartGWT. We really liked the visual components (check out the SmartGWT showcase) and the fact that it facilitates rapid development.

In this tutorial I am going to show you how we created the prototype for our UI in just a few hours. The interface is heavily influenced by the Drools Guvnor application. We use Drools in a lot of our projects and we have Guvnor for the business rules creation. We simply love the user interface, it is both visually beautiful and functionally practical. Check out some Guvnor screenshots.

Let’s get started. I assume you have already installed the GWT SDK and the Google plugin for Eclipse. SmartGWT is compatible with GWT 1.5.3 , GWT 1.6.4, GWT 1.7.x and GWT 2.0.x. Currently, I am using the GWT 2.1.0 SDK and the SmartGWT 2.2 version. In essence, this is a somewhat more advanced tutorial regarding SmartGWT, thus you might have to check my introductory “Getting Started with SmartGWT for awesome GWT interfaces” tutorial. Additionally, another helpful resource is the “Layout the User Interface” tutorial which we used to kick-start the development of our own interface.

First we create a new “Web Application Project” in Eclipse. I chose “AwesomeSmartGWTUIProject” for the project name and “com.javacodegeeks.smartgwt.appui” for the package name.

Next, add the “smartgwt.jar” file from the extracted ZIP to the project’s classpath. Note that this file should also be added to the “war/WEB-INF/lib” directory.

Then edit the module xml file (named “AwesomeSmartGWTUIProject.gwt.xml”) and add the following line after the standard “inherits” declarations:

<inherits name="com.smartgwt.SmartGwt"/>

In addition, comment out the existing section that declares the usage of the GWT theme:

<!--<inherits name='com.google.gwt.user.theme.standard.Standard'/> -->

This is what the module XML file should look like:

<?xml version="1.0" encoding="UTF-8"?>
<module rename-to='awesomesmartgwtuiproject'>
  <!-- Inherit the core Web Toolkit stuff.                        -->
  <inherits name='com.google.gwt.user.User'/>

  <!-- Inherit the default GWT style sheet.  You can change       -->
  <!-- the theme of your GWT application by uncommenting          -->
  <!-- any one of the following lines.                            -->
  
  <!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/>  -->
  <!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
  <!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/>     -->

  <!-- Other module inherits                                      -->
  <inherits name="com.smartgwt.SmartGwt"/>

  <!-- Specify the app entry point class.                         -->
  <entry-point class='com.javacodegeeks.smartgwt.appui.client.AwesomeSmartGWTUIProject'/>

  <!-- Specify the paths for translatable code                    -->
  <source path='client'/>
  <source path='shared'/>

</module>

Next step is to erase some of the auto-generated code that exists in the “AwesomeSmartGWTUIProject.html” file and more specifically the H1 and Table tags. This is what you should be left with:

<!doctype html>
<!-- The DOCTYPE declaration above will set the    -->
<!-- browser's rendering engine into               -->
<!-- "Standards Mode". Replacing this declaration  -->
<!-- with a "Quirks Mode" doctype may lead to some -->
<!-- differences in layout.                        -->

<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">

    <!--                                                               -->
    <!-- Consider inlining CSS to reduce the number of requested files -->
    <!--                                                               -->
    <link type="text/css" rel="stylesheet" href="AwesomeSmartGWTUIProject.css">

    <!--                                           -->
    <!-- Any title is fine                         -->
    <!--                                           -->
    <title>Web Application Starter Project</title>
    
    <!--                                           -->
    <!-- This script loads your compiled module.   -->
    <!-- If you add any GWT meta tags, they must   -->
    <!-- be added before this line.                -->
    <!--                                           -->
    <script type="text/javascript" language="javascript" src="awesomesmartgwtuiproject/awesomesmartgwtuiproject.nocache.js"></script>
  </head>

  <!--                                           -->
  <!-- The body can have arbitrary html, or      -->
  <!-- you can leave the body empty if you want  -->
  <!-- to create a completely dynamic UI.        -->
  <!--                                           -->
  <body>

    <!-- OPTIONAL: include this if you want history support -->
    <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
    
    <!-- RECOMMENDED if your web app will not function without JavaScript enabled -->
    <noscript>
      <div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
        Your web browser must have JavaScript enabled
        in order for this application to display correctly.
      </div>
    </noscript>
    
  </body>
</html>

Similarly, remove all the code existing in your EntryPoint class, named “AwesomeSmartGWTUIProject”, and just leave an empty onModuleLoad method like the following:

package com.javacodegeeks.smartgwt.appui.client;

import com.google.gwt.core.client.EntryPoint;

public class AwesomeSmartGWTUIProject implements EntryPoint {
    
    public void onModuleLoad() {
        
    }
    
}

We are now ready to start writing SmartGWT code, so make sure you have the SmartGWT Javadocs bookmarked. There are two very important classes that we will continually use while building the interface.

  • HLayout: This is a layout related class that applies a sizing policy along the horizontal axis, i.e. all their internal components will be placed in a horizontal manner.
  • VLayout: This is a layout related class that applies a sizing policy along the vertical axis, i.e. all their internal components will be placed in a vertical manner.

Those classes both extend from the parent Layout, thus they inherit the addMember method that allows them to add other Canvas objects or Widgets.

Using various layout objects we will break down the whole screen area to specific sub-areas (north, south, east, west and main). Let’s see how our first version of the entry point class looks like:

package com.javacodegeeks.smartgwt.appui.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.javacodegeeks.smartgwt.appui.client.ui.ApplicationMenu;
import com.javacodegeeks.smartgwt.appui.client.ui.HeaderArea;
import com.javacodegeeks.smartgwt.appui.client.ui.MainArea;
import com.javacodegeeks.smartgwt.appui.client.ui.NavigationArea;
import com.smartgwt.client.widgets.layout.HLayout;
import com.smartgwt.client.widgets.layout.VLayout;

public class AwesomeSmartGWTUIProject implements EntryPoint {
    
    private static final int HEADER_HEIGHT = 85;
    
    private VLayout mainLayout;
    private HLayout northLayout;
    private HLayout southLayout;
    private VLayout eastLayout;
    private HLayout westLayout;
    
    public void onModuleLoad() {
        
        Window.enableScrolling(false);
        Window.setMargin("0px");
        
        // main layout occupies the whole area
        mainLayout = new VLayout();
        mainLayout.setWidth100();
        mainLayout.setHeight100();

        northLayout = new HLayout();
        northLayout.setHeight(HEADER_HEIGHT);

        VLayout vLayout = new VLayout();
        vLayout.addMember(new HeaderArea());
        vLayout.addMember(new ApplicationMenu());
        northLayout.addMember(vLayout);

        westLayout = new NavigationArea();
        westLayout.setWidth("15%");
        
        eastLayout = new MainArea();
        eastLayout.setWidth("85%");
        
        southLayout = new HLayout();
        southLayout.setMembers(westLayout, eastLayout);

        mainLayout.addMember(northLayout);
        mainLayout.addMember(southLayout);

        // add the main layout container to GWT's root panel
        RootLayoutPanel.get().add(mainLayout);

    }
    
}

Don’t worry about the compilation errors, we will create the necessary classes later. As you can see, we have broken the whole screen area to smaller blocks and using the SmartGWT API we have wired all the components together. Note the use of the setWidth100 and setHeight100 methods, which conveniently allow the specific component to occupy the whole available area. Finally, the RootLayoutPanel is the GWT class that gives us access to the root panel of the screen. Let’s now create the various components.

* ApplicationMenu:

package com.javacodegeeks.smartgwt.appui.client.ui;

import com.smartgwt.client.types.Alignment;
import com.smartgwt.client.types.Overflow;
import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.layout.HLayout;

public class ApplicationMenu extends HLayout {

    private static final int APPLICATION_MENU_HEIGHT = 27;

    private Label label;

    public ApplicationMenu() {
        
        super();
        this.setHeight(APPLICATION_MENU_HEIGHT);

        label = new Label();
        label.setContents("Application Menu");
        label.setAlign(Alignment.CENTER);
        label.setOverflow(Overflow.HIDDEN);
        
        this.addMember(label);
        
    }
    
}

Nothing special here, we have just added a Label to the layout and set the Alignment to center.

* HeaderArea:

package com.javacodegeeks.smartgwt.appui.client.ui;

import com.smartgwt.client.types.Alignment;
import com.smartgwt.client.types.Overflow;
import com.smartgwt.client.widgets.Img;
import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.layout.HLayout;

public class HeaderArea extends HLayout {

    private static final int HEADER_AREA_HEIGHT = 60;
    
    public HeaderArea() {

        super();

        this.setHeight(HEADER_AREA_HEIGHT);
        
        Img logo = new Img("jcg_logo.png", 282, 60);

        Label name = new Label();
        name.setOverflow(Overflow.HIDDEN);  
        name.setContents("Java 2 Java Developers Resource Center"); 
        
        HLayout westLayout = new HLayout();
        westLayout.setHeight(HEADER_AREA_HEIGHT);    
        westLayout.setWidth("70%");
        westLayout.addMember(logo);
        westLayout.addMember(name);
        
        Label signedInUser = new Label();
        signedInUser.setContents("Fabrizio Chami");   

        HLayout eastLayout = new HLayout();
        eastLayout.setAlign(Alignment.RIGHT);  
        eastLayout.setHeight(HEADER_AREA_HEIGHT);
        eastLayout.setWidth("30%");
        eastLayout.addMember(signedInUser);
        
        this.addMember(westLayout);      
        this.addMember(eastLayout);

    }

}

Similarly, quite simple. We have added an image using the Img class and providing the file’s name. Note that the image URL falls automatically under an “images” folder, so basically the “jcg_logo.png” file must reside in the “war/images” folder.

* NavigationArea:

package com.javacodegeeks.smartgwt.appui.client;

import com.smartgwt.client.types.Overflow;
import com.smartgwt.client.types.VisibilityMode;
import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.layout.HLayout;
import com.smartgwt.client.widgets.layout.SectionStack;
import com.smartgwt.client.widgets.layout.SectionStackSection;

public class NavigationArea extends HLayout {

    public NavigationArea() {
        
        super();
        
        this.setMembersMargin(20);  
        this.setOverflow(Overflow.HIDDEN);
        this.setShowResizeBar(true);
        
        final SectionStack sectionStack = new SectionStack();  
        sectionStack.setVisibilityMode(VisibilityMode.MULTIPLE);
        sectionStack.setShowExpandControls(true);
        sectionStack.setAnimateSections(true);
        sectionStack.setVisibilityMode(VisibilityMode.MUTEX);
        sectionStack.setOverflow(Overflow.HIDDEN);
        
        SectionStackSection section1 = new SectionStackSection("Section 1");
        section1.setExpanded(true);
        Label label1 = new Label();
        label1.setContents("Label1");
        section1.addItem(label1);
        
        SectionStackSection section2 = new SectionStackSection("Section 2");
        section2.setExpanded(false);
        Label label2 = new Label();
        label2.setContents("Label2");
        label2.setOverflow(Overflow.AUTO);
        label2.setPadding(10);
        section2.addItem(label2);

        SectionStackSection section3 = new SectionStackSection("Section 3");
        section3.setExpanded(false);
        Label label3 = new Label();
        label3.setContents("Label3");
        label3.setOverflow(Overflow.AUTO);
        label3.setPadding(10);
        section3.addItem(label3);

        sectionStack.addSection(section1);
        sectionStack.addSection(section2);
        sectionStack.addSection(section3);
        
        this.addMember(sectionStack);

    }
    
}

For the navigation area we wanted an accordion like component. This is implemented in SmartGWT via the SectionStack class to which we add SectionStackSection instances. To those items we can add arbitrary widgets, but for now we just add some Labels for simplicity. Notice the use of the setShowResizeBar method, which allows us to show a re-size bar after this member in the layout, to allow it to be resized.

* MainArea:

package com.javacodegeeks.smartgwt.appui.client.ui;

import com.smartgwt.client.types.Alignment;
import com.smartgwt.client.types.Overflow;
import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.layout.VLayout;

public class MainArea extends VLayout {
    
    private Label label;
    
    public MainArea() {
        
        super();

        label = new Label();
        label.setContents("Main Area");
        label.setAlign(Alignment.CENTER);
        label.setOverflow(Overflow.HIDDEN);
        
        this.addMember(label);
        
    }

}

The main area will host the bulk of our interface’s widgets, but for now includes only a label.

OK, let’s see what we have done so far. Launch the Eclipse configuration (as a Web Application Project) and point your browser to the provided URL:

http://127.0.0.1:8888/AwesomeSmartGWTUIProject.html?gwt.codesvr=127.0.0.1:9997

This is an image of what you should be seeing:

Not bad for a few minutes of code. Without having to mess with CSS, HTML and JavaScript we have we have created the skeleton of our UI, which consists of strictly defined sub-areas. What is left is to beef it up by populating the areas with various fancy widgets.

In the next part of this tutorial, I am going to introduce you to some of the most advanced components (like trees and tabs). For now, you can find here the Eclipse project created so far. Note that I have removed some of the SmartGWT specific stuff (images etc.) cause they bloated the archive. Those should be automatically created with a new project. The “gwt-servlet.jar” has also been removed from the “war\WEB-INF\lib” directory.

Happy UI coding!

UPDATE: I have also published the second part of this tutorial.

Related Articles :

Ilias Tsagklis

Ilias is a software developer turned online entrepreneur. He is co-founder and Executive Editor at Java Code Geeks.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
raj
raj
10 years ago

good tutorial

Das
10 years ago

This was nice example,I have some other problem here.

I wrote below code,I could not set the panel to the right most side of the container,mu idea is I want control in moving the panel all the sides,like east ,west ,north and south.

public void onModuleLoad() {
Viewport viewport = new Viewport();
viewport.setLayout(new FlowLayout());
viewport.add(createContainer());
RootPanel.get().add(viewport);
}
private Widget createContainer() {
// TODO Auto-generated method stub
LayoutContainer container = new LayoutContainer();
container.setLayout(new BorderLayout());
ContentPanel panel=new ContentPanel(new FitLayout());
panel.setHeading(“The Legend”);
BorderLayoutData westData = new BorderLayoutData(LayoutRegion.WEST, 250);
westData.setSplit(true);
westData.setCollapsible(true);
westData.setMargins(new Margins(0, 3, 0, 0));
container.add(panel,westData);
return container;
}

Can someone help?

Back to top button